<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.3.0">

  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" integrity="sha256-CTSx/A06dm1B063156EVh15m6Y67pAjZZaQc89LLSrU=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.24/fancybox/fancybox.css" integrity="sha256-vQkngPS8jiHHH0I6ABTZroZk8NPZ7b+MUReOFE9UsXQ=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"rjyblog.gitee.io","root":"/","images":"/images","scheme":"Pisces","darkmode":false,"version":"8.18.2","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":null},"fold":{"enable":false,"height":500},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="Flutter启动main函数就是Flutter app的启动入口，在main函数中调用runApp就可以启动我们的界面了： 123void main() &amp;#123;  runApp(const MyApp());&amp;#125;  下面是runApp的源码： 123456789101112131415161718192021222324void runApp(Widget app) &amp;#123;">
<meta property="og:type" content="article">
<meta property="og:title" content="Flutter渲染流程">
<meta property="og:url" content="https://rjyblog.gitee.io/posts/60dc81b5.html">
<meta property="og:site_name" content="任建勇的博客">
<meta property="og:description" content="Flutter启动main函数就是Flutter app的启动入口，在main函数中调用runApp就可以启动我们的界面了： 123void main() &amp;#123;  runApp(const MyApp());&amp;#125;  下面是runApp的源码： 123456789101112131415161718192021222324void runApp(Widget app) &amp;#123;">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2024-01-14T02:23:11.000Z">
<meta property="article:modified_time" content="2024-01-15T03:49:42.259Z">
<meta property="article:author" content="Jason">
<meta property="article:tag" content="Flutter">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="https://rjyblog.gitee.io/posts/60dc81b5.html">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"https://rjyblog.gitee.io/posts/60dc81b5.html","path":"posts/60dc81b5.html","title":"Flutter渲染流程"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>Flutter渲染流程 | 任建勇的博客</title>
  








  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <div class="column">
      <header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">任建勇的博客</p>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger" aria-label="搜索" role="button">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</header>
        
  
  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#Flutter%E5%90%AF%E5%8A%A8"><span class="nav-text">Flutter启动</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%AF%E5%8A%A8%E6%B8%B2%E6%9F%93%E6%B5%81%E7%A8%8B"><span class="nav-text">启动渲染流程</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#C-%E5%B1%82%E7%B1%BB%E5%9B%BE"><span class="nav-text">C++层类图</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B8%A7%E8%B0%83%E5%BA%A6"><span class="nav-text">帧调度</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B8%A7%E7%BB%98%E5%88%B6"><span class="nav-text">帧绘制</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#buildScope%E5%B9%B6markNeedsLayout"><span class="nav-text">buildScope并markNeedsLayout</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#flushLayout"><span class="nav-text">flushLayout</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#flushPaint"><span class="nav-text">flushPaint</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Canvas%E7%BB%98%E5%88%B6"><span class="nav-text">Canvas绘制</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99"><span class="nav-text">参考资料</span></a></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Jason"
      src="/images/avatar.png">
  <p class="site-author-name" itemprop="name">Jason</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">66</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">13</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">23</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>

        </div>
      </div>
    </div>

    
  </aside>


    </div>

    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://rjyblog.gitee.io/posts/60dc81b5.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="Jason">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="任建勇的博客">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="Flutter渲染流程 | 任建勇的博客">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Flutter渲染流程
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2024-01-14 10:23:11" itemprop="dateCreated datePublished" datetime="2024-01-14T10:23:11+08:00">2024-01-14</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">更新于</span>
      <time title="修改时间：2024-01-15 11:49:42" itemprop="dateModified" datetime="2024-01-15T11:49:42+08:00">2024-01-15</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/Flutter/" itemprop="url" rel="index"><span itemprop="name">Flutter</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody"><h2 id="Flutter启动"><a href="#Flutter启动" class="headerlink" title="Flutter启动"></a>Flutter启动</h2><p>main函数就是Flutter app的启动入口，在main函数中调用runApp就可以启动我们的界面了：</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> main() &#123;</span><br><span class="line">  runApp(<span class="keyword">const</span> MyApp());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>下面是runApp的源码：</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> runApp(Widget app) &#123;</span><br><span class="line">  <span class="comment">//binding的初始化</span></span><br><span class="line">  <span class="keyword">final</span> WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();</span><br><span class="line">  <span class="comment">//启动绘制流程</span></span><br><span class="line">  binding</span><br><span class="line">    ..scheduleAttachRootWidget(binding.wrapWithDefaultView(app))</span><br><span class="line">    ..scheduleWarmUpFrame();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">WidgetsFlutterBinding</span> <span class="keyword">extends</span> <span class="title">BindingBase</span> </span></span><br><span class="line"><span class="class">    <span class="title">with</span> <span class="title">GestureBinding</span>, </span></span><br><span class="line"><span class="class">        <span class="title">SchedulerBinding</span>, </span></span><br><span class="line"><span class="class">        <span class="title">ServicesBinding</span>, </span></span><br><span class="line"><span class="class">        <span class="title">PaintingBinding</span>, </span></span><br><span class="line"><span class="class">        <span class="title">SemanticsBinding</span>, </span></span><br><span class="line"><span class="class">        <span class="title">RendererBinding</span>, </span></span><br><span class="line"><span class="class">        <span class="title">WidgetsBinding</span> </span>&#123;</span><br><span class="line">  <span class="keyword">static</span> WidgetsBinding ensureInitialized() &#123;</span><br><span class="line">    <span class="keyword">if</span> (WidgetsBinding._instance == <span class="keyword">null</span>) &#123;</span><br><span class="line">      WidgetsFlutterBinding();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> WidgetsBinding.instance;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>WidgetsFlutterBinding继承自BindingBase，但通过with语句混入了各种Binding，我们都知道mixin的类是没有构造函数的。ensureInitialized()会调用WidgetsFlutterBinding构造函数，主要实现在BindingBase构造函数中。BindingBase在构造函数中会调用initInstances()，这个函数在各个mixin的Binding类中都有实现，首先调用的是WidgetsBinding的实现，然后一层一层调用super.initInstances()，这样所以Binding类的initInstances()都会被执行。下面是initInstances的调用时序：</p>
<pre class="mermaid">

zenuml
WidgetsBinding.initInstances {
    RendererBinding.initInstances {
        SemanticsBinding.initInstances {
            PaintingBinding.initInstances {
                ServicesBinding.initInstances {
                    SchedulerBinding.initInstances {
                        GestureBinding.initInstances {
                            return
                        }
                        return
                    }
                    return
                }
                createImageCache()
                return
            }
            return
        }
        createRootPipelineOwner
        return
    }
    &quot;_buildOwner &#x3D; BuildOwner();&quot;
    &quot;buildOwner!.onBuildScheduled &#x3D; _handleBuildScheduled;&quot;
}
</pre>

<ul>
<li><p>GestureBinding.initInstances：会向PlatformDispatcher设置手势事件的回调，会把从flutter engine接收的数据包解析成PointerEvent，包括PointerDownEvent、PointerUpEvent等；</p>
</li>
<li><p>SchedulerBinding提供了scheduleFrame()接口来主动触发一次绘制刷新。并且还会向PlatformDispatcher注册屏幕刷新事件的回调，如下：</p>
  <figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> ensureFrameCallbacksRegistered() &#123;</span><br><span class="line">platformDispatcher.onBeginFrame ??= _handleBeginFrame;</span><br><span class="line">platformDispatcher.onDrawFrame ??= _handleDrawFrame;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</li>
</ul>
<h3 id="启动渲染流程"><a href="#启动渲染流程" class="headerlink" title="启动渲染流程"></a>启动渲染流程</h3><p>在<code>packages/flutter/lib/src/widgets/binding.dart</code>中的<code>WidgetsBinding.drawFrame()</code>的注释中介绍了渲染流程。</p>
<?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="296px" preserveAspectRatio="none" style="width:503px;height:296px;background:#FFFFFF;" version="1.1" viewBox="0 0 503 296" width="503px" zoomAndPan="magnify"><defs/><g><!--class FlutterView--><g id="elem_FlutterView"><rect codeLine="1" fill="#F1F1F1" height="64.2969" id="FlutterView" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="160" x="7" y="116"/><ellipse cx="42.25" cy="132" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M44.5938,127.6719 C43.6563,127.2344 43.0625,127.0938 42.1875,127.0938 C39.5625,127.0938 37.5625,129.1719 37.5625,131.8906 L37.5625,133.0156 C37.5625,135.5938 39.6719,137.4844 42.5625,137.4844 C43.7813,137.4844 44.9375,137.1875 45.6875,136.6406 C46.2656,136.2344 46.5938,135.7813 46.5938,135.3906 C46.5938,134.9375 46.2031,134.5469 45.7344,134.5469 C45.5156,134.5469 45.3125,134.625 45.125,134.8125 C44.6719,135.2969 44.6719,135.2969 44.4844,135.3906 C44.0625,135.6563 43.375,135.7813 42.6094,135.7813 C40.5625,135.7813 39.2656,134.6875 39.2656,132.9844 L39.2656,131.8906 C39.2656,130.1094 40.5156,128.7969 42.25,128.7969 C42.8281,128.7969 43.4375,128.9531 43.9063,129.2031 C44.3906,129.4844 44.5625,129.7031 44.6563,130.1094 C44.7188,130.5156 44.75,130.6406 44.8906,130.7656 C45.0313,130.9063 45.2656,131.0156 45.4844,131.0156 C45.75,131.0156 46.0156,130.875 46.1875,130.6563 C46.2969,130.5 46.3281,130.3125 46.3281,129.8906 L46.3281,128.4688 C46.3281,128.0313 46.3125,127.9063 46.2188,127.75 C46.0625,127.4844 45.7813,127.3438 45.4844,127.3438 C45.1875,127.3438 44.9844,127.4375 44.7656,127.75 L44.5938,127.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="83" x="60.75" y="136.8467">FlutterView</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="166" y1="148" y2="148"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="166" y1="156" y2="156"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="148" x="13" y="172.9951">render(Scene scene)</text></g><!--class RenderObject--><g id="elem_RenderObject"><rect fill="#F1F1F1" height="48" id="RenderObject" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="133" x="194.5" y="7"/><ellipse cx="209.5" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M211.8438,18.6719 C210.9063,18.2344 210.3125,18.0938 209.4375,18.0938 C206.8125,18.0938 204.8125,20.1719 204.8125,22.8906 L204.8125,24.0156 C204.8125,26.5938 206.9219,28.4844 209.8125,28.4844 C211.0313,28.4844 212.1875,28.1875 212.9375,27.6406 C213.5156,27.2344 213.8438,26.7813 213.8438,26.3906 C213.8438,25.9375 213.4531,25.5469 212.9844,25.5469 C212.7656,25.5469 212.5625,25.625 212.375,25.8125 C211.9219,26.2969 211.9219,26.2969 211.7344,26.3906 C211.3125,26.6563 210.625,26.7813 209.8594,26.7813 C207.8125,26.7813 206.5156,25.6875 206.5156,23.9844 L206.5156,22.8906 C206.5156,21.1094 207.7656,19.7969 209.5,19.7969 C210.0781,19.7969 210.6875,19.9531 211.1563,20.2031 C211.6406,20.4844 211.8125,20.7031 211.9063,21.1094 C211.9688,21.5156 212,21.6406 212.1406,21.7656 C212.2813,21.9063 212.5156,22.0156 212.7344,22.0156 C213,22.0156 213.2656,21.875 213.4375,21.6563 C213.5469,21.5 213.5781,21.3125 213.5781,20.8906 L213.5781,19.4688 C213.5781,19.0313 213.5625,18.9063 213.4688,18.75 C213.3125,18.4844 213.0313,18.3438 212.7344,18.3438 C212.4375,18.3438 212.2344,18.4375 212.0156,18.75 L211.8438,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="101" x="223.5" y="27.8467">RenderObject</text><line style="stroke:#181818;stroke-width:0.5;" x1="195.5" x2="326.5" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="195.5" x2="326.5" y1="47" y2="47"/></g><!--class RenderView--><g id="elem_RenderView"><rect fill="#F1F1F1" height="48" id="RenderView" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="118" x="202" y="124"/><ellipse cx="217" cy="140" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M219.3438,135.6719 C218.4063,135.2344 217.8125,135.0938 216.9375,135.0938 C214.3125,135.0938 212.3125,137.1719 212.3125,139.8906 L212.3125,141.0156 C212.3125,143.5938 214.4219,145.4844 217.3125,145.4844 C218.5313,145.4844 219.6875,145.1875 220.4375,144.6406 C221.0156,144.2344 221.3438,143.7813 221.3438,143.3906 C221.3438,142.9375 220.9531,142.5469 220.4844,142.5469 C220.2656,142.5469 220.0625,142.625 219.875,142.8125 C219.4219,143.2969 219.4219,143.2969 219.2344,143.3906 C218.8125,143.6563 218.125,143.7813 217.3594,143.7813 C215.3125,143.7813 214.0156,142.6875 214.0156,140.9844 L214.0156,139.8906 C214.0156,138.1094 215.2656,136.7969 217,136.7969 C217.5781,136.7969 218.1875,136.9531 218.6563,137.2031 C219.1406,137.4844 219.3125,137.7031 219.4063,138.1094 C219.4688,138.5156 219.5,138.6406 219.6406,138.7656 C219.7813,138.9063 220.0156,139.0156 220.2344,139.0156 C220.5,139.0156 220.7656,138.875 220.9375,138.6563 C221.0469,138.5 221.0781,138.3125 221.0781,137.8906 L221.0781,136.4688 C221.0781,136.0313 221.0625,135.9063 220.9688,135.75 C220.8125,135.4844 220.5313,135.3438 220.2344,135.3438 C219.9375,135.3438 219.7344,135.4375 219.5156,135.75 L219.3438,135.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="86" x="231" y="144.8467">RenderView</text><line style="stroke:#181818;stroke-width:0.5;" x1="203" x2="319" y1="156" y2="156"/><line style="stroke:#181818;stroke-width:0.5;" x1="203" x2="319" y1="164" y2="164"/></g><!--class RenderBox--><g id="elem_RenderBox"><rect fill="#F1F1F1" height="48" id="RenderBox" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="111" x="385.5" y="124"/><ellipse cx="400.5" cy="140" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M402.8438,135.6719 C401.9063,135.2344 401.3125,135.0938 400.4375,135.0938 C397.8125,135.0938 395.8125,137.1719 395.8125,139.8906 L395.8125,141.0156 C395.8125,143.5938 397.9219,145.4844 400.8125,145.4844 C402.0313,145.4844 403.1875,145.1875 403.9375,144.6406 C404.5156,144.2344 404.8438,143.7813 404.8438,143.3906 C404.8438,142.9375 404.4531,142.5469 403.9844,142.5469 C403.7656,142.5469 403.5625,142.625 403.375,142.8125 C402.9219,143.2969 402.9219,143.2969 402.7344,143.3906 C402.3125,143.6563 401.625,143.7813 400.8594,143.7813 C398.8125,143.7813 397.5156,142.6875 397.5156,140.9844 L397.5156,139.8906 C397.5156,138.1094 398.7656,136.7969 400.5,136.7969 C401.0781,136.7969 401.6875,136.9531 402.1563,137.2031 C402.6406,137.4844 402.8125,137.7031 402.9063,138.1094 C402.9688,138.5156 403,138.6406 403.1406,138.7656 C403.2813,138.9063 403.5156,139.0156 403.7344,139.0156 C404,139.0156 404.2656,138.875 404.4375,138.6563 C404.5469,138.5 404.5781,138.3125 404.5781,137.8906 L404.5781,136.4688 C404.5781,136.0313 404.5625,135.9063 404.4688,135.75 C404.3125,135.4844 404.0313,135.3438 403.7344,135.3438 C403.4375,135.3438 403.2344,135.4375 403.0156,135.75 L402.8438,135.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="79" x="414.5" y="144.8467">RenderBox</text><line style="stroke:#181818;stroke-width:0.5;" x1="386.5" x2="495.5" y1="156" y2="156"/><line style="stroke:#181818;stroke-width:0.5;" x1="386.5" x2="495.5" y1="164" y2="164"/></g><!--class Scene--><g id="elem_Scene"><rect fill="#F1F1F1" height="48" id="Scene" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="76" x="49" y="241"/><ellipse cx="64" cy="257" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M66.3438,252.6719 C65.4063,252.2344 64.8125,252.0938 63.9375,252.0938 C61.3125,252.0938 59.3125,254.1719 59.3125,256.8906 L59.3125,258.0156 C59.3125,260.5938 61.4219,262.4844 64.3125,262.4844 C65.5313,262.4844 66.6875,262.1875 67.4375,261.6406 C68.0156,261.2344 68.3438,260.7813 68.3438,260.3906 C68.3438,259.9375 67.9531,259.5469 67.4844,259.5469 C67.2656,259.5469 67.0625,259.625 66.875,259.8125 C66.4219,260.2969 66.4219,260.2969 66.2344,260.3906 C65.8125,260.6563 65.125,260.7813 64.3594,260.7813 C62.3125,260.7813 61.0156,259.6875 61.0156,257.9844 L61.0156,256.8906 C61.0156,255.1094 62.2656,253.7969 64,253.7969 C64.5781,253.7969 65.1875,253.9531 65.6563,254.2031 C66.1406,254.4844 66.3125,254.7031 66.4063,255.1094 C66.4688,255.5156 66.5,255.6406 66.6406,255.7656 C66.7813,255.9063 67.0156,256.0156 67.2344,256.0156 C67.5,256.0156 67.7656,255.875 67.9375,255.6563 C68.0469,255.5 68.0781,255.3125 68.0781,254.8906 L68.0781,253.4688 C68.0781,253.0313 68.0625,252.9063 67.9688,252.75 C67.8125,252.4844 67.5313,252.3438 67.2344,252.3438 C66.9375,252.3438 66.7344,252.4375 66.5156,252.75 L66.3438,252.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="44" x="78" y="261.8467">Scene</text><line style="stroke:#181818;stroke-width:0.5;" x1="50" x2="124" y1="273" y2="273"/><line style="stroke:#181818;stroke-width:0.5;" x1="50" x2="124" y1="281" y2="281"/></g><!--reverse link RenderObject to RenderView--><g id="link_RenderObject_RenderView"><path codeLine="5" d="M261,73.272 C261,93.224 261,103.821 261,123.763 " fill="none" id="RenderObject-backto-RenderView" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="261,55.272,255,73.272,267,73.272,261,55.272" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link RenderView to RenderBox--><g id="link_RenderView_RenderBox"><path codeLine="6" d="M332.438,148 C353.328,148 364.711,148 385.283,148 " fill="none" id="RenderView-backto-RenderBox" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="320.438,148,326.438,152,332.438,148,326.438,144,320.438,148" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="29" x="338.25" y="141.0669">child</text></g><!--link FlutterView to RenderView--><g id="link_FlutterView_RenderView"><path codeLine="7" d="M167.203,148 C178.683,148 178.164,148 189.644,148 " fill="none" id="FlutterView-to-RenderView" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="201.644,148,195.644,144,189.644,148,195.644,152,201.644,148" style="stroke:#181818;stroke-width:1.0;"/></g><!--link FlutterView to Scene--><g id="link_FlutterView_Scene"><path codeLine="8" d="M87,180.121 C87,199.2781 87,217.4234 87,234.8836 " fill="none" id="FlutterView-to-Scene" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="87,240.8836,91,231.8836,87,235.8836,83,231.8836,87,240.8836" style="stroke:#181818;stroke-width:1.0;"/></g><!--SRC=[Iyv9B2vMSCifBIb9BGhBJ2rNgEPI08AYrBoKr2ADuEJKl5I5OX2foLNBnHK45lPFoafDBb6mgT7LLO28W7Ho8PWAMZ09f_mA1Ik5v8pCd1HK-PpKj19TP8kva1sXgskd0BOR0000]--></g></svg>

<?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="186px" preserveAspectRatio="none" style="width:639px;height:186px;background:#FFFFFF;" version="1.1" viewBox="0 0 639 186" width="639px" zoomAndPan="magnify"><defs/><g><!--class RendererBinding--><g id="elem_RendererBinding"><rect codeLine="1" fill="#F1F1F1" height="64.2969" id="RendererBinding" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="153" x="247.5" y="7"/><ellipse cx="262.5" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M264.8438,18.6719 C263.9063,18.2344 263.3125,18.0938 262.4375,18.0938 C259.8125,18.0938 257.8125,20.1719 257.8125,22.8906 L257.8125,24.0156 C257.8125,26.5938 259.9219,28.4844 262.8125,28.4844 C264.0313,28.4844 265.1875,28.1875 265.9375,27.6406 C266.5156,27.2344 266.8438,26.7813 266.8438,26.3906 C266.8438,25.9375 266.4531,25.5469 265.9844,25.5469 C265.7656,25.5469 265.5625,25.625 265.375,25.8125 C264.9219,26.2969 264.9219,26.2969 264.7344,26.3906 C264.3125,26.6563 263.625,26.7813 262.8594,26.7813 C260.8125,26.7813 259.5156,25.6875 259.5156,23.9844 L259.5156,22.8906 C259.5156,21.1094 260.7656,19.7969 262.5,19.7969 C263.0781,19.7969 263.6875,19.9531 264.1563,20.2031 C264.6406,20.4844 264.8125,20.7031 264.9063,21.1094 C264.9688,21.5156 265,21.6406 265.1406,21.7656 C265.2813,21.9063 265.5156,22.0156 265.7344,22.0156 C266,22.0156 266.2656,21.875 266.4375,21.6563 C266.5469,21.5 266.5781,21.3125 266.5781,20.8906 L266.5781,19.4688 C266.5781,19.0313 266.5625,18.9063 266.4688,18.75 C266.3125,18.4844 266.0313,18.3438 265.7344,18.3438 C265.4375,18.3438 265.2344,18.4375 265.0156,18.75 L264.8438,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="121" x="276.5" y="27.8467">RendererBinding</text><line style="stroke:#181818;stroke-width:0.5;" x1="248.5" x2="399.5" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="248.5" x2="399.5" y1="47" y2="47"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="89" x="253.5" y="63.9951">drawFrame()</text></g><!--class PipelineOwner--><g id="elem_PipelineOwner"><rect fill="#F1F1F1" height="48" id="PipelineOwner" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="136" x="7" y="131"/><ellipse cx="22" cy="147" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M24.3438,142.6719 C23.4063,142.2344 22.8125,142.0938 21.9375,142.0938 C19.3125,142.0938 17.3125,144.1719 17.3125,146.8906 L17.3125,148.0156 C17.3125,150.5938 19.4219,152.4844 22.3125,152.4844 C23.5313,152.4844 24.6875,152.1875 25.4375,151.6406 C26.0156,151.2344 26.3438,150.7813 26.3438,150.3906 C26.3438,149.9375 25.9531,149.5469 25.4844,149.5469 C25.2656,149.5469 25.0625,149.625 24.875,149.8125 C24.4219,150.2969 24.4219,150.2969 24.2344,150.3906 C23.8125,150.6563 23.125,150.7813 22.3594,150.7813 C20.3125,150.7813 19.0156,149.6875 19.0156,147.9844 L19.0156,146.8906 C19.0156,145.1094 20.2656,143.7969 22,143.7969 C22.5781,143.7969 23.1875,143.9531 23.6563,144.2031 C24.1406,144.4844 24.3125,144.7031 24.4063,145.1094 C24.4688,145.5156 24.5,145.6406 24.6406,145.7656 C24.7813,145.9063 25.0156,146.0156 25.2344,146.0156 C25.5,146.0156 25.7656,145.875 25.9375,145.6563 C26.0469,145.5 26.0781,145.3125 26.0781,144.8906 L26.0781,143.4688 C26.0781,143.0313 26.0625,142.9063 25.9688,142.75 C25.8125,142.4844 25.5313,142.3438 25.2344,142.3438 C24.9375,142.3438 24.7344,142.4375 24.5156,142.75 L24.3438,142.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="104" x="36" y="151.8467">PipelineOwner</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="142" y1="163" y2="163"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="142" y1="171" y2="171"/></g><!--class RenderView--><g id="elem_RenderView"><rect fill="#F1F1F1" height="48" id="RenderView" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="118" x="514" y="131"/><ellipse cx="529" cy="147" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M531.3438,142.6719 C530.4063,142.2344 529.8125,142.0938 528.9375,142.0938 C526.3125,142.0938 524.3125,144.1719 524.3125,146.8906 L524.3125,148.0156 C524.3125,150.5938 526.4219,152.4844 529.3125,152.4844 C530.5313,152.4844 531.6875,152.1875 532.4375,151.6406 C533.0156,151.2344 533.3438,150.7813 533.3438,150.3906 C533.3438,149.9375 532.9531,149.5469 532.4844,149.5469 C532.2656,149.5469 532.0625,149.625 531.875,149.8125 C531.4219,150.2969 531.4219,150.2969 531.2344,150.3906 C530.8125,150.6563 530.125,150.7813 529.3594,150.7813 C527.3125,150.7813 526.0156,149.6875 526.0156,147.9844 L526.0156,146.8906 C526.0156,145.1094 527.2656,143.7969 529,143.7969 C529.5781,143.7969 530.1875,143.9531 530.6563,144.2031 C531.1406,144.4844 531.3125,144.7031 531.4063,145.1094 C531.4688,145.5156 531.5,145.6406 531.6406,145.7656 C531.7813,145.9063 532.0156,146.0156 532.2344,146.0156 C532.5,146.0156 532.7656,145.875 532.9375,145.6563 C533.0469,145.5 533.0781,145.3125 533.0781,144.8906 L533.0781,143.4688 C533.0781,143.0313 533.0625,142.9063 532.9688,142.75 C532.8125,142.4844 532.5313,142.3438 532.2344,142.3438 C531.9375,142.3438 531.7344,142.4375 531.5156,142.75 L531.3438,142.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="86" x="543" y="151.8467">RenderView</text><line style="stroke:#181818;stroke-width:0.5;" x1="515" x2="631" y1="163" y2="163"/><line style="stroke:#181818;stroke-width:0.5;" x1="515" x2="631" y1="171" y2="171"/></g><!--class AbstractNode--><g id="elem_AbstractNode"><rect fill="#F1F1F1" height="48" id="AbstractNode" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="132" x="178" y="131"/><ellipse cx="193" cy="147" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M195.3438,142.6719 C194.4063,142.2344 193.8125,142.0938 192.9375,142.0938 C190.3125,142.0938 188.3125,144.1719 188.3125,146.8906 L188.3125,148.0156 C188.3125,150.5938 190.4219,152.4844 193.3125,152.4844 C194.5313,152.4844 195.6875,152.1875 196.4375,151.6406 C197.0156,151.2344 197.3438,150.7813 197.3438,150.3906 C197.3438,149.9375 196.9531,149.5469 196.4844,149.5469 C196.2656,149.5469 196.0625,149.625 195.875,149.8125 C195.4219,150.2969 195.4219,150.2969 195.2344,150.3906 C194.8125,150.6563 194.125,150.7813 193.3594,150.7813 C191.3125,150.7813 190.0156,149.6875 190.0156,147.9844 L190.0156,146.8906 C190.0156,145.1094 191.2656,143.7969 193,143.7969 C193.5781,143.7969 194.1875,143.9531 194.6563,144.2031 C195.1406,144.4844 195.3125,144.7031 195.4063,145.1094 C195.4688,145.5156 195.5,145.6406 195.6406,145.7656 C195.7813,145.9063 196.0156,146.0156 196.2344,146.0156 C196.5,146.0156 196.7656,145.875 196.9375,145.6563 C197.0469,145.5 197.0781,145.3125 197.0781,144.8906 L197.0781,143.4688 C197.0781,143.0313 197.0625,142.9063 196.9688,142.75 C196.8125,142.4844 196.5313,142.3438 196.2344,142.3438 C195.9375,142.3438 195.7344,142.4375 195.5156,142.75 L195.3438,142.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="100" x="207" y="151.8467">AbstractNode</text><line style="stroke:#181818;stroke-width:0.5;" x1="179" x2="309" y1="163" y2="163"/><line style="stroke:#181818;stroke-width:0.5;" x1="179" x2="309" y1="171" y2="171"/></g><!--class RenderObject--><g id="elem_RenderObject"><rect fill="#F1F1F1" height="48" id="RenderObject" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="133" x="345.5" y="131"/><ellipse cx="360.5" cy="147" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M362.8438,142.6719 C361.9063,142.2344 361.3125,142.0938 360.4375,142.0938 C357.8125,142.0938 355.8125,144.1719 355.8125,146.8906 L355.8125,148.0156 C355.8125,150.5938 357.9219,152.4844 360.8125,152.4844 C362.0313,152.4844 363.1875,152.1875 363.9375,151.6406 C364.5156,151.2344 364.8438,150.7813 364.8438,150.3906 C364.8438,149.9375 364.4531,149.5469 363.9844,149.5469 C363.7656,149.5469 363.5625,149.625 363.375,149.8125 C362.9219,150.2969 362.9219,150.2969 362.7344,150.3906 C362.3125,150.6563 361.625,150.7813 360.8594,150.7813 C358.8125,150.7813 357.5156,149.6875 357.5156,147.9844 L357.5156,146.8906 C357.5156,145.1094 358.7656,143.7969 360.5,143.7969 C361.0781,143.7969 361.6875,143.9531 362.1563,144.2031 C362.6406,144.4844 362.8125,144.7031 362.9063,145.1094 C362.9688,145.5156 363,145.6406 363.1406,145.7656 C363.2813,145.9063 363.5156,146.0156 363.7344,146.0156 C364,146.0156 364.2656,145.875 364.4375,145.6563 C364.5469,145.5 364.5781,145.3125 364.5781,144.8906 L364.5781,143.4688 C364.5781,143.0313 364.5625,142.9063 364.4688,142.75 C364.3125,142.4844 364.0313,142.3438 363.7344,142.3438 C363.4375,142.3438 363.2344,142.4375 363.0156,142.75 L362.8438,142.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="101" x="374.5" y="151.8467">RenderObject</text><line style="stroke:#181818;stroke-width:0.5;" x1="346.5" x2="477.5" y1="163" y2="163"/><line style="stroke:#181818;stroke-width:0.5;" x1="346.5" x2="477.5" y1="171" y2="171"/></g><!--reverse link RendererBinding to PipelineOwner--><g id="link_RendererBinding_PipelineOwner"><path codeLine="4" d="M245.3782,75.9954 C204.0462,94.9186 162.999,113.7113 125.315,130.9644 " fill="none" id="RendererBinding-backto-PipelineOwner" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="256.289,71,249.1685,69.8607,245.3782,75.9954,252.4987,77.1346,256.289,71" style="stroke:#181818;stroke-width:1.0;"/></g><!--link RendererBinding to RenderView--><g id="link_RendererBinding_RenderView"><path codeLine="5" d="M391.711,71 C433.043,89.9232 479.5456,111.2136 517.2296,128.4667 " fill="none" id="RendererBinding-to-RenderView" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="522.685,130.9644,516.167,123.5809,518.1388,128.883,512.8368,130.8548,522.685,130.9644" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link PipelineOwner to AbstractNode--><g id="link_PipelineOwner_AbstractNode"><path codeLine="6" d="M155.326,155 C166.862,155 166.397,155 177.933,155 " fill="none" id="PipelineOwner-backto-AbstractNode" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="143.326,155,149.326,159,155.326,155,149.326,151,143.326,155" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link AbstractNode to RenderObject--><g id="link_AbstractNode_RenderObject"><path codeLine="7" d="M328.281,155 C339.937,155 333.592,155 345.247,155 " fill="none" id="AbstractNode-backto-RenderObject" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="310.281,155,328.281,161,328.281,149,310.281,155" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link RenderObject to RenderView--><g id="link_RenderObject_RenderView"><path codeLine="8" d="M496.664,155 C508.333,155 502.002,155 513.672,155 " fill="none" id="RenderObject-backto-RenderView" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="478.664,155,496.664,161,496.664,149,478.664,155" style="stroke:#181818;stroke-width:1.0;"/></g><!--SRC=[Iyv9B2vM24hDIqajIYrooinBoSnBLwZcKW22bAB4ShUYnDnK3KskMYvqDLgwkWe1cGMfEPbvgVxbUQb562fqTUsW9eTbffPpeIW6QbTmJ2ekAKfCBl7BJqdbGkOesDJeGdNw9sMb9fTm8NEGP47c0W00]--></g></svg>

<p>绘制UI需要一个画布（Canvas）来进行绘制，然后PictureRecorder会生成一个Picture，并保存到PictureLayer中。</p>
<?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="170px" preserveAspectRatio="none" style="width:438px;height:170px;background:#FFFFFF;" version="1.1" viewBox="0 0 438 170" width="438px" zoomAndPan="magnify"><defs/><g><!--class Canvas--><g id="elem_Canvas"><rect fill="#F1F1F1" height="48" id="Canvas" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="82" x="7" y="7"/><ellipse cx="22" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M24.3438,18.6719 C23.4063,18.2344 22.8125,18.0938 21.9375,18.0938 C19.3125,18.0938 17.3125,20.1719 17.3125,22.8906 L17.3125,24.0156 C17.3125,26.5938 19.4219,28.4844 22.3125,28.4844 C23.5313,28.4844 24.6875,28.1875 25.4375,27.6406 C26.0156,27.2344 26.3438,26.7813 26.3438,26.3906 C26.3438,25.9375 25.9531,25.5469 25.4844,25.5469 C25.2656,25.5469 25.0625,25.625 24.875,25.8125 C24.4219,26.2969 24.4219,26.2969 24.2344,26.3906 C23.8125,26.6563 23.125,26.7813 22.3594,26.7813 C20.3125,26.7813 19.0156,25.6875 19.0156,23.9844 L19.0156,22.8906 C19.0156,21.1094 20.2656,19.7969 22,19.7969 C22.5781,19.7969 23.1875,19.9531 23.6563,20.2031 C24.1406,20.4844 24.3125,20.7031 24.4063,21.1094 C24.4688,21.5156 24.5,21.6406 24.6406,21.7656 C24.7813,21.9063 25.0156,22.0156 25.2344,22.0156 C25.5,22.0156 25.7656,21.875 25.9375,21.6563 C26.0469,21.5 26.0781,21.3125 26.0781,20.8906 L26.0781,19.4688 C26.0781,19.0313 26.0625,18.9063 25.9688,18.75 C25.8125,18.4844 25.5313,18.3438 25.2344,18.3438 C24.9375,18.3438 24.7344,18.4375 24.5156,18.75 L24.3438,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="36" y="27.8467">Canvas</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="88" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="88" y1="47" y2="47"/></g><!--class PictureRecorder--><g id="elem_PictureRecorder"><rect fill="#F1F1F1" height="48" id="PictureRecorder" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="149" x="124.5" y="7"/><ellipse cx="139.5" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M141.8438,18.6719 C140.9063,18.2344 140.3125,18.0938 139.4375,18.0938 C136.8125,18.0938 134.8125,20.1719 134.8125,22.8906 L134.8125,24.0156 C134.8125,26.5938 136.9219,28.4844 139.8125,28.4844 C141.0313,28.4844 142.1875,28.1875 142.9375,27.6406 C143.5156,27.2344 143.8438,26.7813 143.8438,26.3906 C143.8438,25.9375 143.4531,25.5469 142.9844,25.5469 C142.7656,25.5469 142.5625,25.625 142.375,25.8125 C141.9219,26.2969 141.9219,26.2969 141.7344,26.3906 C141.3125,26.6563 140.625,26.7813 139.8594,26.7813 C137.8125,26.7813 136.5156,25.6875 136.5156,23.9844 L136.5156,22.8906 C136.5156,21.1094 137.7656,19.7969 139.5,19.7969 C140.0781,19.7969 140.6875,19.9531 141.1563,20.2031 C141.6406,20.4844 141.8125,20.7031 141.9063,21.1094 C141.9688,21.5156 142,21.6406 142.1406,21.7656 C142.2813,21.9063 142.5156,22.0156 142.7344,22.0156 C143,22.0156 143.2656,21.875 143.4375,21.6563 C143.5469,21.5 143.5781,21.3125 143.5781,20.8906 L143.5781,19.4688 C143.5781,19.0313 143.5625,18.9063 143.4688,18.75 C143.3125,18.4844 143.0313,18.3438 142.7344,18.3438 C142.4375,18.3438 142.2344,18.4375 142.0156,18.75 L141.8438,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="117" x="153.5" y="27.8467">PictureRecorder</text><line style="stroke:#181818;stroke-width:0.5;" x1="125.5" x2="272.5" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="125.5" x2="272.5" y1="47" y2="47"/></g><!--class Picture--><g id="elem_Picture"><rect fill="#F1F1F1" height="48" id="Picture" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="83" x="242.5" y="115"/><ellipse cx="257.5" cy="131" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M259.8438,126.6719 C258.9063,126.2344 258.3125,126.0938 257.4375,126.0938 C254.8125,126.0938 252.8125,128.1719 252.8125,130.8906 L252.8125,132.0156 C252.8125,134.5938 254.9219,136.4844 257.8125,136.4844 C259.0313,136.4844 260.1875,136.1875 260.9375,135.6406 C261.5156,135.2344 261.8438,134.7813 261.8438,134.3906 C261.8438,133.9375 261.4531,133.5469 260.9844,133.5469 C260.7656,133.5469 260.5625,133.625 260.375,133.8125 C259.9219,134.2969 259.9219,134.2969 259.7344,134.3906 C259.3125,134.6563 258.625,134.7813 257.8594,134.7813 C255.8125,134.7813 254.5156,133.6875 254.5156,131.9844 L254.5156,130.8906 C254.5156,129.1094 255.7656,127.7969 257.5,127.7969 C258.0781,127.7969 258.6875,127.9531 259.1563,128.2031 C259.6406,128.4844 259.8125,128.7031 259.9063,129.1094 C259.9688,129.5156 260,129.6406 260.1406,129.7656 C260.2813,129.9063 260.5156,130.0156 260.7344,130.0156 C261,130.0156 261.2656,129.875 261.4375,129.6563 C261.5469,129.5 261.5781,129.3125 261.5781,128.8906 L261.5781,127.4688 C261.5781,127.0313 261.5625,126.9063 261.4688,126.75 C261.3125,126.4844 261.0313,126.3438 260.7344,126.3438 C260.4375,126.3438 260.2344,126.4375 260.0156,126.75 L259.8438,126.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="51" x="271.5" y="135.8467">Picture</text><line style="stroke:#181818;stroke-width:0.5;" x1="243.5" x2="324.5" y1="147" y2="147"/><line style="stroke:#181818;stroke-width:0.5;" x1="243.5" x2="324.5" y1="155" y2="155"/></g><!--class PictureLayer--><g id="elem_PictureLayer"><rect fill="#F1F1F1" height="48" id="PictureLayer" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="122" x="309" y="7"/><ellipse cx="324" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M326.3438,18.6719 C325.4063,18.2344 324.8125,18.0938 323.9375,18.0938 C321.3125,18.0938 319.3125,20.1719 319.3125,22.8906 L319.3125,24.0156 C319.3125,26.5938 321.4219,28.4844 324.3125,28.4844 C325.5313,28.4844 326.6875,28.1875 327.4375,27.6406 C328.0156,27.2344 328.3438,26.7813 328.3438,26.3906 C328.3438,25.9375 327.9531,25.5469 327.4844,25.5469 C327.2656,25.5469 327.0625,25.625 326.875,25.8125 C326.4219,26.2969 326.4219,26.2969 326.2344,26.3906 C325.8125,26.6563 325.125,26.7813 324.3594,26.7813 C322.3125,26.7813 321.0156,25.6875 321.0156,23.9844 L321.0156,22.8906 C321.0156,21.1094 322.2656,19.7969 324,19.7969 C324.5781,19.7969 325.1875,19.9531 325.6563,20.2031 C326.1406,20.4844 326.3125,20.7031 326.4063,21.1094 C326.4688,21.5156 326.5,21.6406 326.6406,21.7656 C326.7813,21.9063 327.0156,22.0156 327.2344,22.0156 C327.5,22.0156 327.7656,21.875 327.9375,21.6563 C328.0469,21.5 328.0781,21.3125 328.0781,20.8906 L328.0781,19.4688 C328.0781,19.0313 328.0625,18.9063 327.9688,18.75 C327.8125,18.4844 327.5313,18.3438 327.2344,18.3438 C326.9375,18.3438 326.7344,18.4375 326.5156,18.75 L326.3438,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="90" x="338" y="27.8467">PictureLayer</text><line style="stroke:#181818;stroke-width:0.5;" x1="310" x2="430" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="310" x2="430" y1="47" y2="47"/></g><!--reverse link Canvas to PictureRecorder--><g id="link_Canvas_PictureRecorder"><path codeLine="1" d="M101.0184,47.8383 C112.7323,50.3693 112.717,49.066 124.431,48.997 " fill="none" id="Canvas-backto-PictureRecorder" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="89.2891,45.304,94.309,50.4809,101.0184,47.8383,95.9985,42.6614,89.2891,45.304" style="stroke:#181818;stroke-width:1.0;"/></g><!--link Canvas to PictureRecorder--><g id="link_Canvas_PictureRecorder"><path codeLine="2" d="M89.2891,16.696 C101.003,14.165 100.7172,12.8633 112.4312,12.9323 " fill="none" id="Canvas-to-PictureRecorder" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="124.431,13.003,118.4547,8.9677,112.4312,12.9323,118.4075,16.9676,124.431,13.003" style="stroke:#181818;stroke-width:1.0;"/></g><!--link PictureRecorder to Picture--><g id="link_PictureRecorder_Picture"><path codeLine="3" d="M217.444,55 C231.603,72.6584 247.3214,92.26 261.5454,109.9976 " fill="none" id="PictureRecorder-to-Picture" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="265.299,114.6784,262.7891,105.1547,262.171,110.7777,256.548,110.1596,265.299,114.6784" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link PictureLayer to Picture--><g id="link_PictureLayer_Picture"><path codeLine="4" d="M343.7787,64.3189 C329.4527,81.9773 317.312,96.9408 302.921,114.6784 " fill="none" id="PictureLayer-backto-Picture" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="351.339,55,344.4526,57.1394,343.7787,64.3189,350.6652,62.1795,351.339,55" style="stroke:#181818;stroke-width:1.0;"/></g><!--SRC=[SqxCAqiiLj3ILGZ8J2ufBKeDIatEBqf9BU9oXiZeQc78eF4LT7NjO6fWSZw9bK09BLsuiG00]--></g></svg>

<h3 id="C-层类图"><a href="#C-层类图" class="headerlink" title="C++层类图"></a>C++层类图</h3><?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="311px" preserveAspectRatio="none" style="width:409px;height:311px;background:#FFFFFF;" version="1.1" viewBox="0 0 409 311" width="409px" zoomAndPan="magnify"><defs/><g><!--class PictureRecorder--><g id="elem_PictureRecorder"><rect codeLine="1" fill="#F1F1F1" height="80.5938" id="PictureRecorder" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="268" x="109" y="7"/><ellipse cx="180.25" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M182.5938,18.6719 C181.6563,18.2344 181.0625,18.0938 180.1875,18.0938 C177.5625,18.0938 175.5625,20.1719 175.5625,22.8906 L175.5625,24.0156 C175.5625,26.5938 177.6719,28.4844 180.5625,28.4844 C181.7813,28.4844 182.9375,28.1875 183.6875,27.6406 C184.2656,27.2344 184.5938,26.7813 184.5938,26.3906 C184.5938,25.9375 184.2031,25.5469 183.7344,25.5469 C183.5156,25.5469 183.3125,25.625 183.125,25.8125 C182.6719,26.2969 182.6719,26.2969 182.4844,26.3906 C182.0625,26.6563 181.375,26.7813 180.6094,26.7813 C178.5625,26.7813 177.2656,25.6875 177.2656,23.9844 L177.2656,22.8906 C177.2656,21.1094 178.5156,19.7969 180.25,19.7969 C180.8281,19.7969 181.4375,19.9531 181.9063,20.2031 C182.3906,20.4844 182.5625,20.7031 182.6563,21.1094 C182.7188,21.5156 182.75,21.6406 182.8906,21.7656 C183.0313,21.9063 183.2656,22.0156 183.4844,22.0156 C183.75,22.0156 184.0156,21.875 184.1875,21.6563 C184.2969,21.5 184.3281,21.3125 184.3281,20.8906 L184.3281,19.4688 C184.3281,19.0313 184.3125,18.9063 184.2188,18.75 C184.0625,18.4844 183.7813,18.3438 183.4844,18.3438 C183.1875,18.3438 182.9844,18.4375 182.7656,18.75 L182.5938,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="117" x="200.75" y="27.8467">PictureRecorder</text><line style="stroke:#181818;stroke-width:0.5;" x1="110" x2="376" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="110" x2="376" y1="47" y2="47"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="256" x="115" y="63.9951">DisplayListBuilder BeginRecording()</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="165" x="115" y="80.292">Picture endRecording()</text></g><!--class DisplayListBuilder--><g id="elem_DisplayListBuilder"><rect fill="#F1F1F1" height="48" id="DisplayListBuilder" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="160" x="7" y="148"/><ellipse cx="22" cy="164" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M24.3438,159.6719 C23.4063,159.2344 22.8125,159.0938 21.9375,159.0938 C19.3125,159.0938 17.3125,161.1719 17.3125,163.8906 L17.3125,165.0156 C17.3125,167.5938 19.4219,169.4844 22.3125,169.4844 C23.5313,169.4844 24.6875,169.1875 25.4375,168.6406 C26.0156,168.2344 26.3438,167.7813 26.3438,167.3906 C26.3438,166.9375 25.9531,166.5469 25.4844,166.5469 C25.2656,166.5469 25.0625,166.625 24.875,166.8125 C24.4219,167.2969 24.4219,167.2969 24.2344,167.3906 C23.8125,167.6563 23.125,167.7813 22.3594,167.7813 C20.3125,167.7813 19.0156,166.6875 19.0156,164.9844 L19.0156,163.8906 C19.0156,162.1094 20.2656,160.7969 22,160.7969 C22.5781,160.7969 23.1875,160.9531 23.6563,161.2031 C24.1406,161.4844 24.3125,161.7031 24.4063,162.1094 C24.4688,162.5156 24.5,162.6406 24.6406,162.7656 C24.7813,162.9063 25.0156,163.0156 25.2344,163.0156 C25.5,163.0156 25.7656,162.875 25.9375,162.6563 C26.0469,162.5 26.0781,162.3125 26.0781,161.8906 L26.0781,160.4688 C26.0781,160.0313 26.0625,159.9063 25.9688,159.75 C25.8125,159.4844 25.5313,159.3438 25.2344,159.3438 C24.9375,159.3438 24.7344,159.4375 24.5156,159.75 L24.3438,159.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="128" x="36" y="168.8467">DisplayListBuilder</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="166" y1="180" y2="180"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="166" y1="188" y2="188"/></g><!--class Canvas--><g id="elem_Canvas"><rect fill="#F1F1F1" height="48" id="Canvas" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="82" x="202" y="148"/><ellipse cx="217" cy="164" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M219.3438,159.6719 C218.4063,159.2344 217.8125,159.0938 216.9375,159.0938 C214.3125,159.0938 212.3125,161.1719 212.3125,163.8906 L212.3125,165.0156 C212.3125,167.5938 214.4219,169.4844 217.3125,169.4844 C218.5313,169.4844 219.6875,169.1875 220.4375,168.6406 C221.0156,168.2344 221.3438,167.7813 221.3438,167.3906 C221.3438,166.9375 220.9531,166.5469 220.4844,166.5469 C220.2656,166.5469 220.0625,166.625 219.875,166.8125 C219.4219,167.2969 219.4219,167.2969 219.2344,167.3906 C218.8125,167.6563 218.125,167.7813 217.3594,167.7813 C215.3125,167.7813 214.0156,166.6875 214.0156,164.9844 L214.0156,163.8906 C214.0156,162.1094 215.2656,160.7969 217,160.7969 C217.5781,160.7969 218.1875,160.9531 218.6563,161.2031 C219.1406,161.4844 219.3125,161.7031 219.4063,162.1094 C219.4688,162.5156 219.5,162.6406 219.6406,162.7656 C219.7813,162.9063 220.0156,163.0156 220.2344,163.0156 C220.5,163.0156 220.7656,162.875 220.9375,162.6563 C221.0469,162.5 221.0781,162.3125 221.0781,161.8906 L221.0781,160.4688 C221.0781,160.0313 221.0625,159.9063 220.9688,159.75 C220.8125,159.4844 220.5313,159.3438 220.2344,159.3438 C219.9375,159.3438 219.7344,159.4375 219.5156,159.75 L219.3438,159.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="231" y="168.8467">Canvas</text><line style="stroke:#181818;stroke-width:0.5;" x1="203" x2="283" y1="180" y2="180"/><line style="stroke:#181818;stroke-width:0.5;" x1="203" x2="283" y1="188" y2="188"/></g><!--class Picture--><g id="elem_Picture"><rect fill="#F1F1F1" height="48" id="Picture" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="83" x="319.5" y="148"/><ellipse cx="334.5" cy="164" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M336.8438,159.6719 C335.9063,159.2344 335.3125,159.0938 334.4375,159.0938 C331.8125,159.0938 329.8125,161.1719 329.8125,163.8906 L329.8125,165.0156 C329.8125,167.5938 331.9219,169.4844 334.8125,169.4844 C336.0313,169.4844 337.1875,169.1875 337.9375,168.6406 C338.5156,168.2344 338.8438,167.7813 338.8438,167.3906 C338.8438,166.9375 338.4531,166.5469 337.9844,166.5469 C337.7656,166.5469 337.5625,166.625 337.375,166.8125 C336.9219,167.2969 336.9219,167.2969 336.7344,167.3906 C336.3125,167.6563 335.625,167.7813 334.8594,167.7813 C332.8125,167.7813 331.5156,166.6875 331.5156,164.9844 L331.5156,163.8906 C331.5156,162.1094 332.7656,160.7969 334.5,160.7969 C335.0781,160.7969 335.6875,160.9531 336.1563,161.2031 C336.6406,161.4844 336.8125,161.7031 336.9063,162.1094 C336.9688,162.5156 337,162.6406 337.1406,162.7656 C337.2813,162.9063 337.5156,163.0156 337.7344,163.0156 C338,163.0156 338.2656,162.875 338.4375,162.6563 C338.5469,162.5 338.5781,162.3125 338.5781,161.8906 L338.5781,160.4688 C338.5781,160.0313 338.5625,159.9063 338.4688,159.75 C338.3125,159.4844 338.0313,159.3438 337.7344,159.3438 C337.4375,159.3438 337.2344,159.4375 337.0156,159.75 L336.8438,159.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="51" x="348.5" y="168.8467">Picture</text><line style="stroke:#181818;stroke-width:0.5;" x1="320.5" x2="401.5" y1="180" y2="180"/><line style="stroke:#181818;stroke-width:0.5;" x1="320.5" x2="401.5" y1="188" y2="188"/></g><!--class DisplayList--><g id="elem_DisplayList"><rect fill="#F1F1F1" height="48" id="DisplayList" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="110" x="169" y="256"/><ellipse cx="184" cy="272" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M186.3438,267.6719 C185.4063,267.2344 184.8125,267.0938 183.9375,267.0938 C181.3125,267.0938 179.3125,269.1719 179.3125,271.8906 L179.3125,273.0156 C179.3125,275.5938 181.4219,277.4844 184.3125,277.4844 C185.5313,277.4844 186.6875,277.1875 187.4375,276.6406 C188.0156,276.2344 188.3438,275.7813 188.3438,275.3906 C188.3438,274.9375 187.9531,274.5469 187.4844,274.5469 C187.2656,274.5469 187.0625,274.625 186.875,274.8125 C186.4219,275.2969 186.4219,275.2969 186.2344,275.3906 C185.8125,275.6563 185.125,275.7813 184.3594,275.7813 C182.3125,275.7813 181.0156,274.6875 181.0156,272.9844 L181.0156,271.8906 C181.0156,270.1094 182.2656,268.7969 184,268.7969 C184.5781,268.7969 185.1875,268.9531 185.6563,269.2031 C186.1406,269.4844 186.3125,269.7031 186.4063,270.1094 C186.4688,270.5156 186.5,270.6406 186.6406,270.7656 C186.7813,270.9063 187.0156,271.0156 187.2344,271.0156 C187.5,271.0156 187.7656,270.875 187.9375,270.6563 C188.0469,270.5 188.0781,270.3125 188.0781,269.8906 L188.0781,268.4688 C188.0781,268.0313 188.0625,267.9063 187.9688,267.75 C187.8125,267.4844 187.5313,267.3438 187.2344,267.3438 C186.9375,267.3438 186.7344,267.4375 186.5156,267.75 L186.3438,267.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="78" x="198" y="276.8467">DisplayList</text><line style="stroke:#181818;stroke-width:0.5;" x1="170" x2="278" y1="288" y2="288"/><line style="stroke:#181818;stroke-width:0.5;" x1="170" x2="278" y1="296" y2="296"/></g><!--reverse link PictureRecorder to DisplayListBuilder--><g id="link_PictureRecorder_DisplayListBuilder"><path codeLine="5" d="M182.9132,95.6833 C157.8252,115.3843 137.851,131.069 116.49,147.843 " fill="none" id="PictureRecorder-backto-DisplayListBuilder" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="192.351,88.272,185.1617,88.8317,182.9132,95.6833,190.1025,95.1236,192.351,88.272" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link PictureRecorder to Canvas--><g id="link_PictureRecorder_Canvas"><path codeLine="6" d="M230.1349,100.2426 C228.7539,119.9436 230.188,131.069 232.761,147.843 " fill="none" id="PictureRecorder-backto-Canvas" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="230.974,88.272,226.5642,93.9776,230.1349,100.2426,234.5447,94.537,230.974,88.272" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link Canvas to PictureRecorder--><g id="link_Canvas_PictureRecorder"><path codeLine="7" d="M255.7655,135.9982 C258.4895,119.2242 257.196,107.973 255.733,88.272 " fill="none" id="Canvas-backto-PictureRecorder" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="253.842,147.843,258.752,142.5618,255.7655,135.9982,250.8555,141.2794,253.842,147.843" style="stroke:#181818;stroke-width:1.0;"/></g><!--link PictureRecorder to Picture--><g id="link_PictureRecorder_Picture"><path codeLine="8" d="M281.311,88.272 C300.289,107.973 318.3736,126.7476 334.5306,143.5216 " fill="none" id="PictureRecorder-to-Picture" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="338.693,147.843,335.3303,138.586,335.2243,144.2419,329.5685,144.1359,338.693,147.843" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link Picture to DisplayList--><g id="link_Picture_DisplayList"><path codeLine="9" d="M321.7823,203.3434 C298.9603,221.0018 277.067,237.9408 254.142,255.6784 " fill="none" id="Picture-backto-DisplayList" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="331.273,196,324.0798,196.5081,321.7823,203.3434,328.9754,202.8353,331.273,196" style="stroke:#181818;stroke-width:1.0;"/></g><!--link DisplayListBuilder to DisplayList--><g id="link_DisplayListBuilder_DisplayList"><path codeLine="10" d="M116.727,196 C139.549,213.6584 166.1876,234.2692 189.1126,252.0068 " fill="none" id="DisplayListBuilder-to-DisplayList" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="193.858,255.6784,189.1876,247.0073,189.9035,252.6187,184.2921,253.3346,193.858,255.6784" style="stroke:#181818;stroke-width:1.0;"/></g><!--SRC=[Iyv9B2vM2CXCBYajIWrAJSulIaajKgZcKW02bypYWfp4If_CuXAdqimSa8HJQdfc7aHPPbwwXYPO7LItGcfU2h9KBHUwiLgwkbWCnQhCEJ6lBB6O2qA1HT1KOUZIrRM3gO79eLl8XSL786r8mW00]--></g></svg>

<p>PictureRecorder在<code>【flutter_engine】\lib\ui\painting\picture_recorder.h</code>中声明。</p>
<?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="507px" preserveAspectRatio="none" style="width:976px;height:507px;background:#FFFFFF;" version="1.1" viewBox="0 0 976 507" width="976px" zoomAndPan="magnify"><defs/><g><!--class RenderObjectWidget--><g id="elem_RenderObjectWidget"><rect fill="#F1F1F1" height="48" id="RenderObjectWidget" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="185" x="446.5" y="7"/><ellipse cx="461.5" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M463.8438,18.6719 C462.9063,18.2344 462.3125,18.0938 461.4375,18.0938 C458.8125,18.0938 456.8125,20.1719 456.8125,22.8906 L456.8125,24.0156 C456.8125,26.5938 458.9219,28.4844 461.8125,28.4844 C463.0313,28.4844 464.1875,28.1875 464.9375,27.6406 C465.5156,27.2344 465.8438,26.7813 465.8438,26.3906 C465.8438,25.9375 465.4531,25.5469 464.9844,25.5469 C464.7656,25.5469 464.5625,25.625 464.375,25.8125 C463.9219,26.2969 463.9219,26.2969 463.7344,26.3906 C463.3125,26.6563 462.625,26.7813 461.8594,26.7813 C459.8125,26.7813 458.5156,25.6875 458.5156,23.9844 L458.5156,22.8906 C458.5156,21.1094 459.7656,19.7969 461.5,19.7969 C462.0781,19.7969 462.6875,19.9531 463.1563,20.2031 C463.6406,20.4844 463.8125,20.7031 463.9063,21.1094 C463.9688,21.5156 464,21.6406 464.1406,21.7656 C464.2813,21.9063 464.5156,22.0156 464.7344,22.0156 C465,22.0156 465.2656,21.875 465.4375,21.6563 C465.5469,21.5 465.5781,21.3125 465.5781,20.8906 L465.5781,19.4688 C465.5781,19.0313 465.5625,18.9063 465.4688,18.75 C465.3125,18.4844 465.0313,18.3438 464.7344,18.3438 C464.4375,18.3438 464.2344,18.4375 464.0156,18.75 L463.8438,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="153" x="475.5" y="27.8467">RenderObjectWidget</text><line style="stroke:#181818;stroke-width:0.5;" x1="447.5" x2="630.5" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="447.5" x2="630.5" y1="47" y2="47"/></g><!--class RenderObjectToWidgetAdapter--><g id="elem_RenderObjectToWidgetAdapter"><rect fill="#F1F1F1" height="48" id="RenderObjectToWidgetAdapter" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="262" x="408" y="116"/><ellipse cx="423" cy="132" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M425.3438,127.6719 C424.4063,127.2344 423.8125,127.0938 422.9375,127.0938 C420.3125,127.0938 418.3125,129.1719 418.3125,131.8906 L418.3125,133.0156 C418.3125,135.5938 420.4219,137.4844 423.3125,137.4844 C424.5313,137.4844 425.6875,137.1875 426.4375,136.6406 C427.0156,136.2344 427.3438,135.7813 427.3438,135.3906 C427.3438,134.9375 426.9531,134.5469 426.4844,134.5469 C426.2656,134.5469 426.0625,134.625 425.875,134.8125 C425.4219,135.2969 425.4219,135.2969 425.2344,135.3906 C424.8125,135.6563 424.125,135.7813 423.3594,135.7813 C421.3125,135.7813 420.0156,134.6875 420.0156,132.9844 L420.0156,131.8906 C420.0156,130.1094 421.2656,128.7969 423,128.7969 C423.5781,128.7969 424.1875,128.9531 424.6563,129.2031 C425.1406,129.4844 425.3125,129.7031 425.4063,130.1094 C425.4688,130.5156 425.5,130.6406 425.6406,130.7656 C425.7813,130.9063 426.0156,131.0156 426.2344,131.0156 C426.5,131.0156 426.7656,130.875 426.9375,130.6563 C427.0469,130.5 427.0781,130.3125 427.0781,129.8906 L427.0781,128.4688 C427.0781,128.0313 427.0625,127.9063 426.9688,127.75 C426.8125,127.4844 426.5313,127.3438 426.2344,127.3438 C425.9375,127.3438 425.7344,127.4375 425.5156,127.75 L425.3438,127.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="230" x="437" y="136.8467">RenderObjectToWidgetAdapter</text><line style="stroke:#181818;stroke-width:0.5;" x1="409" x2="669" y1="148" y2="148"/><line style="stroke:#181818;stroke-width:0.5;" x1="409" x2="669" y1="156" y2="156"/></g><!--class RenderObjectToWidgetElement--><g id="elem_RenderObjectToWidgetElement"><rect fill="#F1F1F1" height="48" id="RenderObjectToWidgetElement" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="264" x="705" y="116"/><ellipse cx="720" cy="132" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M722.3438,127.6719 C721.4063,127.2344 720.8125,127.0938 719.9375,127.0938 C717.3125,127.0938 715.3125,129.1719 715.3125,131.8906 L715.3125,133.0156 C715.3125,135.5938 717.4219,137.4844 720.3125,137.4844 C721.5313,137.4844 722.6875,137.1875 723.4375,136.6406 C724.0156,136.2344 724.3438,135.7813 724.3438,135.3906 C724.3438,134.9375 723.9531,134.5469 723.4844,134.5469 C723.2656,134.5469 723.0625,134.625 722.875,134.8125 C722.4219,135.2969 722.4219,135.2969 722.2344,135.3906 C721.8125,135.6563 721.125,135.7813 720.3594,135.7813 C718.3125,135.7813 717.0156,134.6875 717.0156,132.9844 L717.0156,131.8906 C717.0156,130.1094 718.2656,128.7969 720,128.7969 C720.5781,128.7969 721.1875,128.9531 721.6563,129.2031 C722.1406,129.4844 722.3125,129.7031 722.4063,130.1094 C722.4688,130.5156 722.5,130.6406 722.6406,130.7656 C722.7813,130.9063 723.0156,131.0156 723.2344,131.0156 C723.5,131.0156 723.7656,130.875 723.9375,130.6563 C724.0469,130.5 724.0781,130.3125 724.0781,129.8906 L724.0781,128.4688 C724.0781,128.0313 724.0625,127.9063 723.9688,127.75 C723.8125,127.4844 723.5313,127.3438 723.2344,127.3438 C722.9375,127.3438 722.7344,127.4375 722.5156,127.75 L722.3438,127.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="232" x="734" y="136.8467">RenderObjectToWidgetElement</text><line style="stroke:#181818;stroke-width:0.5;" x1="706" x2="968" y1="148" y2="148"/><line style="stroke:#181818;stroke-width:0.5;" x1="706" x2="968" y1="156" y2="156"/></g><!--class RenderObjectElement--><g id="elem_RenderObjectElement"><rect fill="#F1F1F1" height="48" id="RenderObjectElement" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="194" x="740" y="7"/><ellipse cx="755" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M757.3438,18.6719 C756.4063,18.2344 755.8125,18.0938 754.9375,18.0938 C752.3125,18.0938 750.3125,20.1719 750.3125,22.8906 L750.3125,24.0156 C750.3125,26.5938 752.4219,28.4844 755.3125,28.4844 C756.5313,28.4844 757.6875,28.1875 758.4375,27.6406 C759.0156,27.2344 759.3438,26.7813 759.3438,26.3906 C759.3438,25.9375 758.9531,25.5469 758.4844,25.5469 C758.2656,25.5469 758.0625,25.625 757.875,25.8125 C757.4219,26.2969 757.4219,26.2969 757.2344,26.3906 C756.8125,26.6563 756.125,26.7813 755.3594,26.7813 C753.3125,26.7813 752.0156,25.6875 752.0156,23.9844 L752.0156,22.8906 C752.0156,21.1094 753.2656,19.7969 755,19.7969 C755.5781,19.7969 756.1875,19.9531 756.6563,20.2031 C757.1406,20.4844 757.3125,20.7031 757.4063,21.1094 C757.4688,21.5156 757.5,21.6406 757.6406,21.7656 C757.7813,21.9063 758.0156,22.0156 758.2344,22.0156 C758.5,22.0156 758.7656,21.875 758.9375,21.6563 C759.0469,21.5 759.0781,21.3125 759.0781,20.8906 L759.0781,19.4688 C759.0781,19.0313 759.0625,18.9063 758.9688,18.75 C758.8125,18.4844 758.5313,18.3438 758.2344,18.3438 C757.9375,18.3438 757.7344,18.4375 757.5156,18.75 L757.3438,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="162" x="769" y="27.8467">RenderObjectElement</text><line style="stroke:#181818;stroke-width:0.5;" x1="741" x2="933" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="741" x2="933" y1="47" y2="47"/></g><!--class StatelessWidget--><g id="elem_StatelessWidget"><rect fill="#F1F1F1" height="48" id="StatelessWidget" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="151" x="221.5" y="116"/><ellipse cx="236.5" cy="132" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M238.8438,127.6719 C237.9063,127.2344 237.3125,127.0938 236.4375,127.0938 C233.8125,127.0938 231.8125,129.1719 231.8125,131.8906 L231.8125,133.0156 C231.8125,135.5938 233.9219,137.4844 236.8125,137.4844 C238.0313,137.4844 239.1875,137.1875 239.9375,136.6406 C240.5156,136.2344 240.8438,135.7813 240.8438,135.3906 C240.8438,134.9375 240.4531,134.5469 239.9844,134.5469 C239.7656,134.5469 239.5625,134.625 239.375,134.8125 C238.9219,135.2969 238.9219,135.2969 238.7344,135.3906 C238.3125,135.6563 237.625,135.7813 236.8594,135.7813 C234.8125,135.7813 233.5156,134.6875 233.5156,132.9844 L233.5156,131.8906 C233.5156,130.1094 234.7656,128.7969 236.5,128.7969 C237.0781,128.7969 237.6875,128.9531 238.1563,129.2031 C238.6406,129.4844 238.8125,129.7031 238.9063,130.1094 C238.9688,130.5156 239,130.6406 239.1406,130.7656 C239.2813,130.9063 239.5156,131.0156 239.7344,131.0156 C240,131.0156 240.2656,130.875 240.4375,130.6563 C240.5469,130.5 240.5781,130.3125 240.5781,129.8906 L240.5781,128.4688 C240.5781,128.0313 240.5625,127.9063 240.4688,127.75 C240.3125,127.4844 240.0313,127.3438 239.7344,127.3438 C239.4375,127.3438 239.2344,127.4375 239.0156,127.75 L238.8438,127.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="119" x="250.5" y="136.8467">StatelessWidget</text><line style="stroke:#181818;stroke-width:0.5;" x1="222.5" x2="371.5" y1="148" y2="148"/><line style="stroke:#181818;stroke-width:0.5;" x1="222.5" x2="371.5" y1="156" y2="156"/></g><!--class View--><g id="elem_View"><rect fill="#F1F1F1" height="48" id="View" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="66" x="274" y="241"/><ellipse cx="289" cy="257" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M291.3438,252.6719 C290.4063,252.2344 289.8125,252.0938 288.9375,252.0938 C286.3125,252.0938 284.3125,254.1719 284.3125,256.8906 L284.3125,258.0156 C284.3125,260.5938 286.4219,262.4844 289.3125,262.4844 C290.5313,262.4844 291.6875,262.1875 292.4375,261.6406 C293.0156,261.2344 293.3438,260.7813 293.3438,260.3906 C293.3438,259.9375 292.9531,259.5469 292.4844,259.5469 C292.2656,259.5469 292.0625,259.625 291.875,259.8125 C291.4219,260.2969 291.4219,260.2969 291.2344,260.3906 C290.8125,260.6563 290.125,260.7813 289.3594,260.7813 C287.3125,260.7813 286.0156,259.6875 286.0156,257.9844 L286.0156,256.8906 C286.0156,255.1094 287.2656,253.7969 289,253.7969 C289.5781,253.7969 290.1875,253.9531 290.6563,254.2031 C291.1406,254.4844 291.3125,254.7031 291.4063,255.1094 C291.4688,255.5156 291.5,255.6406 291.6406,255.7656 C291.7813,255.9063 292.0156,256.0156 292.2344,256.0156 C292.5,256.0156 292.7656,255.875 292.9375,255.6563 C293.0469,255.5 293.0781,255.3125 293.0781,254.8906 L293.0781,253.4688 C293.0781,253.0313 293.0625,252.9063 292.9688,252.75 C292.8125,252.4844 292.5313,252.3438 292.2344,252.3438 C291.9375,252.3438 291.7344,252.4375 291.5156,252.75 L291.3438,252.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="34" x="303" y="261.8467">View</text><line style="stroke:#181818;stroke-width:0.5;" x1="275" x2="339" y1="273" y2="273"/><line style="stroke:#181818;stroke-width:0.5;" x1="275" x2="339" y1="281" y2="281"/></g><!--class FlutterView--><g id="elem_FlutterView"><rect fill="#F1F1F1" height="48" id="FlutterView" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="115" x="158.5" y="366"/><ellipse cx="173.5" cy="382" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M175.8438,377.6719 C174.9063,377.2344 174.3125,377.0938 173.4375,377.0938 C170.8125,377.0938 168.8125,379.1719 168.8125,381.8906 L168.8125,383.0156 C168.8125,385.5938 170.9219,387.4844 173.8125,387.4844 C175.0313,387.4844 176.1875,387.1875 176.9375,386.6406 C177.5156,386.2344 177.8438,385.7813 177.8438,385.3906 C177.8438,384.9375 177.4531,384.5469 176.9844,384.5469 C176.7656,384.5469 176.5625,384.625 176.375,384.8125 C175.9219,385.2969 175.9219,385.2969 175.7344,385.3906 C175.3125,385.6563 174.625,385.7813 173.8594,385.7813 C171.8125,385.7813 170.5156,384.6875 170.5156,382.9844 L170.5156,381.8906 C170.5156,380.1094 171.7656,378.7969 173.5,378.7969 C174.0781,378.7969 174.6875,378.9531 175.1563,379.2031 C175.6406,379.4844 175.8125,379.7031 175.9063,380.1094 C175.9688,380.5156 176,380.6406 176.1406,380.7656 C176.2813,380.9063 176.5156,381.0156 176.7344,381.0156 C177,381.0156 177.2656,380.875 177.4375,380.6563 C177.5469,380.5 177.5781,380.3125 177.5781,379.8906 L177.5781,378.4688 C177.5781,378.0313 177.5625,377.9063 177.4688,377.75 C177.3125,377.4844 177.0313,377.3438 176.7344,377.3438 C176.4375,377.3438 176.2344,377.4375 176.0156,377.75 L175.8438,377.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="83" x="187.5" y="386.8467">FlutterView</text><line style="stroke:#181818;stroke-width:0.5;" x1="159.5" x2="272.5" y1="398" y2="398"/><line style="stroke:#181818;stroke-width:0.5;" x1="159.5" x2="272.5" y1="406" y2="406"/></g><!--class MyApp--><g id="elem_MyApp"><rect fill="#F1F1F1" height="48" id="MyApp" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="82" x="309" y="366"/><ellipse cx="324" cy="382" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M326.3438,377.6719 C325.4063,377.2344 324.8125,377.0938 323.9375,377.0938 C321.3125,377.0938 319.3125,379.1719 319.3125,381.8906 L319.3125,383.0156 C319.3125,385.5938 321.4219,387.4844 324.3125,387.4844 C325.5313,387.4844 326.6875,387.1875 327.4375,386.6406 C328.0156,386.2344 328.3438,385.7813 328.3438,385.3906 C328.3438,384.9375 327.9531,384.5469 327.4844,384.5469 C327.2656,384.5469 327.0625,384.625 326.875,384.8125 C326.4219,385.2969 326.4219,385.2969 326.2344,385.3906 C325.8125,385.6563 325.125,385.7813 324.3594,385.7813 C322.3125,385.7813 321.0156,384.6875 321.0156,382.9844 L321.0156,381.8906 C321.0156,380.1094 322.2656,378.7969 324,378.7969 C324.5781,378.7969 325.1875,378.9531 325.6563,379.2031 C326.1406,379.4844 326.3125,379.7031 326.4063,380.1094 C326.4688,380.5156 326.5,380.6406 326.6406,380.7656 C326.7813,380.9063 327.0156,381.0156 327.2344,381.0156 C327.5,381.0156 327.7656,380.875 327.9375,380.6563 C328.0469,380.5 328.0781,380.3125 328.0781,379.8906 L328.0781,378.4688 C328.0781,378.0313 328.0625,377.9063 327.9688,377.75 C327.8125,377.4844 327.5313,377.3438 327.2344,377.3438 C326.9375,377.3438 326.7344,377.4375 326.5156,377.75 L326.3438,377.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="338" y="386.8467">MyApp</text><line style="stroke:#181818;stroke-width:0.5;" x1="310" x2="390" y1="398" y2="398"/><line style="stroke:#181818;stroke-width:0.5;" x1="310" x2="390" y1="406" y2="406"/></g><g id="elem_GMN16"><path d="M291,475 L291,500.1328 A0,0 0 0 0 291,500.1328 L409,500.1328 A0,0 0 0 0 409,500.1328 L409,485 L399,475 L354,475 L350,414.1179 L346,475 L291,475 A0,0 0 0 0 291,475 " fill="#FEFFDD" style="stroke:#181818;stroke-width:0.5;"/><path d="M399,475 L399,485 L409,485 L399,475 " fill="#FEFFDD" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="97" x="297" y="492.0669">&#29992;&#25143;&#23618;&#26681;Widget</text></g><!--class InheritedWidget--><g id="elem_InheritedWidget"><rect fill="#F1F1F1" height="48" id="InheritedWidget" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="150" x="16" y="116"/><ellipse cx="31" cy="132" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M33.3438,127.6719 C32.4063,127.2344 31.8125,127.0938 30.9375,127.0938 C28.3125,127.0938 26.3125,129.1719 26.3125,131.8906 L26.3125,133.0156 C26.3125,135.5938 28.4219,137.4844 31.3125,137.4844 C32.5313,137.4844 33.6875,137.1875 34.4375,136.6406 C35.0156,136.2344 35.3438,135.7813 35.3438,135.3906 C35.3438,134.9375 34.9531,134.5469 34.4844,134.5469 C34.2656,134.5469 34.0625,134.625 33.875,134.8125 C33.4219,135.2969 33.4219,135.2969 33.2344,135.3906 C32.8125,135.6563 32.125,135.7813 31.3594,135.7813 C29.3125,135.7813 28.0156,134.6875 28.0156,132.9844 L28.0156,131.8906 C28.0156,130.1094 29.2656,128.7969 31,128.7969 C31.5781,128.7969 32.1875,128.9531 32.6563,129.2031 C33.1406,129.4844 33.3125,129.7031 33.4063,130.1094 C33.4688,130.5156 33.5,130.6406 33.6406,130.7656 C33.7813,130.9063 34.0156,131.0156 34.2344,131.0156 C34.5,131.0156 34.7656,130.875 34.9375,130.6563 C35.0469,130.5 35.0781,130.3125 35.0781,129.8906 L35.0781,128.4688 C35.0781,128.0313 35.0625,127.9063 34.9688,127.75 C34.8125,127.4844 34.5313,127.3438 34.2344,127.3438 C33.9375,127.3438 33.7344,127.4375 33.5156,127.75 L33.3438,127.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="118" x="45" y="136.8467">InheritedWidget</text><line style="stroke:#181818;stroke-width:0.5;" x1="17" x2="165" y1="148" y2="148"/><line style="stroke:#181818;stroke-width:0.5;" x1="17" x2="165" y1="156" y2="156"/></g><!--class _ViewScope--><g id="elem__ViewScope"><rect fill="#F1F1F1" height="48" id="_ViewScope" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="118" x="32" y="241"/><ellipse cx="47" cy="257" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M49.3438,252.6719 C48.4063,252.2344 47.8125,252.0938 46.9375,252.0938 C44.3125,252.0938 42.3125,254.1719 42.3125,256.8906 L42.3125,258.0156 C42.3125,260.5938 44.4219,262.4844 47.3125,262.4844 C48.5313,262.4844 49.6875,262.1875 50.4375,261.6406 C51.0156,261.2344 51.3438,260.7813 51.3438,260.3906 C51.3438,259.9375 50.9531,259.5469 50.4844,259.5469 C50.2656,259.5469 50.0625,259.625 49.875,259.8125 C49.4219,260.2969 49.4219,260.2969 49.2344,260.3906 C48.8125,260.6563 48.125,260.7813 47.3594,260.7813 C45.3125,260.7813 44.0156,259.6875 44.0156,257.9844 L44.0156,256.8906 C44.0156,255.1094 45.2656,253.7969 47,253.7969 C47.5781,253.7969 48.1875,253.9531 48.6563,254.2031 C49.1406,254.4844 49.3125,254.7031 49.4063,255.1094 C49.4688,255.5156 49.5,255.6406 49.6406,255.7656 C49.7813,255.9063 50.0156,256.0156 50.2344,256.0156 C50.5,256.0156 50.7656,255.875 50.9375,255.6563 C51.0469,255.5 51.0781,255.3125 51.0781,254.8906 L51.0781,253.4688 C51.0781,253.0313 51.0625,252.9063 50.9688,252.75 C50.8125,252.4844 50.5313,252.3438 50.2344,252.3438 C49.9375,252.3438 49.7344,252.4375 49.5156,252.75 L49.3438,252.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="86" x="61" y="261.8467">_ViewScope</text><line style="stroke:#181818;stroke-width:0.5;" x1="33" x2="149" y1="273" y2="273"/><line style="stroke:#181818;stroke-width:0.5;" x1="33" x2="149" y1="281" y2="281"/></g><!--class MediaQuery--><g id="elem_MediaQuery"><rect fill="#F1F1F1" height="48" id="MediaQuery" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="116" x="7" y="366"/><ellipse cx="22" cy="382" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M24.3438,377.6719 C23.4063,377.2344 22.8125,377.0938 21.9375,377.0938 C19.3125,377.0938 17.3125,379.1719 17.3125,381.8906 L17.3125,383.0156 C17.3125,385.5938 19.4219,387.4844 22.3125,387.4844 C23.5313,387.4844 24.6875,387.1875 25.4375,386.6406 C26.0156,386.2344 26.3438,385.7813 26.3438,385.3906 C26.3438,384.9375 25.9531,384.5469 25.4844,384.5469 C25.2656,384.5469 25.0625,384.625 24.875,384.8125 C24.4219,385.2969 24.4219,385.2969 24.2344,385.3906 C23.8125,385.6563 23.125,385.7813 22.3594,385.7813 C20.3125,385.7813 19.0156,384.6875 19.0156,382.9844 L19.0156,381.8906 C19.0156,380.1094 20.2656,378.7969 22,378.7969 C22.5781,378.7969 23.1875,378.9531 23.6563,379.2031 C24.1406,379.4844 24.3125,379.7031 24.4063,380.1094 C24.4688,380.5156 24.5,380.6406 24.6406,380.7656 C24.7813,380.9063 25.0156,381.0156 25.2344,381.0156 C25.5,381.0156 25.7656,380.875 25.9375,380.6563 C26.0469,380.5 26.0781,380.3125 26.0781,379.8906 L26.0781,378.4688 C26.0781,378.0313 26.0625,377.9063 25.9688,377.75 C25.8125,377.4844 25.5313,377.3438 25.2344,377.3438 C24.9375,377.3438 24.7344,377.4375 24.5156,377.75 L24.3438,377.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="84" x="36" y="386.8467">MediaQuery</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="122" y1="398" y2="398"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="122" y1="406" y2="406"/></g><!--class RenderObjectWithChildMixin--><g id="elem_RenderObjectWithChildMixin"><rect fill="#F1F1F1" height="48" id="RenderObjectWithChildMixin" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="240" x="419" y="241"/><ellipse cx="434" cy="257" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M436.3438,252.6719 C435.4063,252.2344 434.8125,252.0938 433.9375,252.0938 C431.3125,252.0938 429.3125,254.1719 429.3125,256.8906 L429.3125,258.0156 C429.3125,260.5938 431.4219,262.4844 434.3125,262.4844 C435.5313,262.4844 436.6875,262.1875 437.4375,261.6406 C438.0156,261.2344 438.3438,260.7813 438.3438,260.3906 C438.3438,259.9375 437.9531,259.5469 437.4844,259.5469 C437.2656,259.5469 437.0625,259.625 436.875,259.8125 C436.4219,260.2969 436.4219,260.2969 436.2344,260.3906 C435.8125,260.6563 435.125,260.7813 434.3594,260.7813 C432.3125,260.7813 431.0156,259.6875 431.0156,257.9844 L431.0156,256.8906 C431.0156,255.1094 432.2656,253.7969 434,253.7969 C434.5781,253.7969 435.1875,253.9531 435.6563,254.2031 C436.1406,254.4844 436.3125,254.7031 436.4063,255.1094 C436.4688,255.5156 436.5,255.6406 436.6406,255.7656 C436.7813,255.9063 437.0156,256.0156 437.2344,256.0156 C437.5,256.0156 437.7656,255.875 437.9375,255.6563 C438.0469,255.5 438.0781,255.3125 438.0781,254.8906 L438.0781,253.4688 C438.0781,253.0313 438.0625,252.9063 437.9688,252.75 C437.8125,252.4844 437.5313,252.3438 437.2344,252.3438 C436.9375,252.3438 436.7344,252.4375 436.5156,252.75 L436.3438,252.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="208" x="448" y="261.8467">RenderObjectWithChildMixin</text><line style="stroke:#181818;stroke-width:0.5;" x1="420" x2="658" y1="273" y2="273"/><line style="stroke:#181818;stroke-width:0.5;" x1="420" x2="658" y1="281" y2="281"/></g><!--class RenderView--><g id="elem_RenderView"><rect fill="#F1F1F1" height="48" id="RenderView" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="118" x="480" y="366"/><ellipse cx="495" cy="382" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M497.3438,377.6719 C496.4063,377.2344 495.8125,377.0938 494.9375,377.0938 C492.3125,377.0938 490.3125,379.1719 490.3125,381.8906 L490.3125,383.0156 C490.3125,385.5938 492.4219,387.4844 495.3125,387.4844 C496.5313,387.4844 497.6875,387.1875 498.4375,386.6406 C499.0156,386.2344 499.3438,385.7813 499.3438,385.3906 C499.3438,384.9375 498.9531,384.5469 498.4844,384.5469 C498.2656,384.5469 498.0625,384.625 497.875,384.8125 C497.4219,385.2969 497.4219,385.2969 497.2344,385.3906 C496.8125,385.6563 496.125,385.7813 495.3594,385.7813 C493.3125,385.7813 492.0156,384.6875 492.0156,382.9844 L492.0156,381.8906 C492.0156,380.1094 493.2656,378.7969 495,378.7969 C495.5781,378.7969 496.1875,378.9531 496.6563,379.2031 C497.1406,379.4844 497.3125,379.7031 497.4063,380.1094 C497.4688,380.5156 497.5,380.6406 497.6406,380.7656 C497.7813,380.9063 498.0156,381.0156 498.2344,381.0156 C498.5,381.0156 498.7656,380.875 498.9375,380.6563 C499.0469,380.5 499.0781,380.3125 499.0781,379.8906 L499.0781,378.4688 C499.0781,378.0313 499.0625,377.9063 498.9688,377.75 C498.8125,377.4844 498.5313,377.3438 498.2344,377.3438 C497.9375,377.3438 497.7344,377.4375 497.5156,377.75 L497.3438,377.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="86" x="509" y="386.8467">RenderView</text><line style="stroke:#181818;stroke-width:0.5;" x1="481" x2="597" y1="398" y2="398"/><line style="stroke:#181818;stroke-width:0.5;" x1="481" x2="597" y1="406" y2="406"/></g><!--reverse link RenderObjectWidget to RenderObjectToWidgetAdapter--><g id="link_RenderObjectWidget_RenderObjectToWidgetAdapter"><path codeLine="1" d="M539,73.217 C539,91.165 539,97.892 539,115.828 " fill="none" id="RenderObjectWidget-backto-RenderObjectToWidgetAdapter" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="539,55.217,533,73.217,545,73.217,539,55.217" style="stroke:#181818;stroke-width:1.0;"/></g><!--link RenderObjectToWidgetAdapter to RenderObjectToWidgetElement--><g id="link_RenderObjectToWidgetAdapter_RenderObjectToWidgetElement"><path codeLine="2" d="M670.248,140 C681.756,140 687.263,140 698.771,140 " fill="none" id="RenderObjectToWidgetAdapter-to-RenderObjectToWidgetElement" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="704.771,140,695.771,136,699.771,140,695.771,144,704.771,140" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link RenderObjectElement to RenderObjectToWidgetElement--><g id="link_RenderObjectElement_RenderObjectToWidgetElement"><path codeLine="3" d="M837,73.217 C837,91.165 837,97.892 837,115.828 " fill="none" id="RenderObjectElement-backto-RenderObjectToWidgetElement" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="837,55.217,831,73.217,843,73.217,837,55.217" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link StatelessWidget to View--><g id="link_StatelessWidget_View"><path codeLine="5" d="M300.3397,182.0758 C302.1277,204.0668 303.342,219.012 305.128,240.968 " fill="none" id="StatelessWidget-backto-View" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="298.881,164.135,294.3594,182.562,306.32,181.5896,298.881,164.135" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link View to FlutterView--><g id="link_View_FlutterView"><path codeLine="6" d="M282.7468,298.7818 C266.4768,320.7728 249.284,344.012 233.04,365.968 " fill="none" id="View-backto-FlutterView" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="289.884,289.135,283.0998,291.5793,282.7468,298.7818,289.531,296.3375,289.884,289.135" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link View to MyApp--><g id="link_View_MyApp"><path codeLine="7" d="M319.0481,300.4627 C326.7361,322.4537 334.273,344.012 341.948,365.968 " fill="none" id="View-backto-MyApp" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="315.088,289.135,313.2922,296.1189,319.0481,300.4627,320.844,293.4788,315.088,289.135" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="29" x="333" y="332.0669">child</text></g><!--reverse link InheritedWidget to _ViewScope--><g id="link_InheritedWidget__ViewScope"><path codeLine="11" d="M91,182.135 C91,204.126 91,219.012 91,240.968 " fill="none" id="InheritedWidget-backto-_ViewScope" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="91,164.135,85,182.135,97,182.135,91,164.135" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link _ViewScope to FlutterView--><g id="link__ViewScope_FlutterView"><path codeLine="12" d="M123.0653,297.5517 C145.4133,319.5427 170.281,344.012 192.594,365.968 " fill="none" id="_ViewScope-backto-FlutterView" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="114.512,289.135,115.9831,296.1945,123.0653,297.5517,121.5942,290.4922,114.512,289.135" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link _ViewScope to MediaQuery--><g id="link__ViewScope_MediaQuery"><path codeLine="13" d="M83.6279,300.8756 C78.9795,322.8666 74.5096,344.012 69.8685,365.968 " fill="none" id="_ViewScope-backto-MediaQuery" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="86.1096,289.135,80.9552,294.1781,83.6279,300.8756,88.7823,295.8325,86.1096,289.135" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="29" x="81" y="332.0669">child</text></g><!--reverse link MediaQuery to MyApp--><g id="link_MediaQuery_MyApp"><path codeLine="14" d="M107.6637,359.3378 C141.1462,337.5298 185.011,317.074 233.5,329 C262.764,336.198 292.823,352.191 315.077,365.996 " fill="none" id="MediaQuery-backto-MyApp" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="97.6085,365.887,104.8192,365.9641,107.6637,359.3378,100.453,359.2606,97.6085,365.887" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="29" x="203.5" y="332.0669">child</text></g><!--reverse link RenderObjectToWidgetAdapter to View--><g id="link_RenderObjectToWidgetAdapter_View"><path codeLine="16" d="M484.7609,169.7561 C439.7389,193.6261 381.105,224.712 340.304,246.343 " fill="none" id="RenderObjectToWidgetAdapter-backto-View" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="495.363,164.135,488.1883,163.4115,484.7609,169.7561,491.9357,170.4795,495.363,164.135" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link RenderObjectToWidgetAdapter to RenderObjectWithChildMixin--><g id="link_RenderObjectToWidgetAdapter_RenderObjectWithChildMixin"><path codeLine="17" d="M539,176.135 C539,198.126 539,219.012 539,240.968 " fill="none" id="RenderObjectToWidgetAdapter-backto-RenderObjectWithChildMixin" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="539,164.135,535,170.135,539,176.135,543,170.135,539,164.135" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="60" x="540" y="207.0669">container</text></g><!--reverse link RenderObjectWithChildMixin to RenderView--><g id="link_RenderObjectWithChildMixin_RenderView"><path codeLine="18" d="M539,307.135 C539,329.126 539,344.012 539,365.968 " fill="none" id="RenderObjectWithChildMixin-backto-RenderView" style="stroke:#181818;stroke-width:1.0;stroke-dasharray:7.0,7.0;"/><polygon fill="none" points="539,289.135,533,307.135,545,307.135,539,289.135" style="stroke:#181818;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="27" x="540" y="332.0669">with</text></g><!--SRC=[XL7D3i504BxlKyovIJs0Y4I4nA4H9HobkaDNQhUf4IHEJXx00pYwEea7mclegf-sgCjcz_k- -URR6Hibnx0v6ADBFS57I51QcIRO2RoZOgR2dO0mP3aScEMlfJKV9oWfLVh0VlTx5h4sEOG-JgV9X5s1SwOFCA9NtPzHr3yDMijA440HN4_ud4b520D5f2QWXZ79hjlzPNCy7zQNtIbsPr4IBMKDwM4e27coQr-RjrqL87jVFn9aA0kvS5ep39UlC0d8o0RD7R3n_Fe_aPtQB7bLxMs9XP2waPBa29bPPaPMMXKA3vlxI8imZmGt]--></g></svg>

<h2 id="帧调度"><a href="#帧调度" class="headerlink" title="帧调度"></a>帧调度</h2><p>我们在自定义的StatefulWidget调用setState就会触发UI重绘，我们以此为起点进行渲染流程的分析。我们先概述一下绘制的基本流程，然后再进行详细的流程和代码分析。有一个大局观之后再看细节更容易理解：</p>
<ol>
<li><code>setState</code>会调用<code>Element.markNeedsBuild()</code>，会调用到SchedulerBinding.scheduleFrame来通知引擎要进行下一帧的绘制，然后把对应的Element添加到_dirtyElements这个需要重绘的脏列表中；</li>
<li>应用层接收到引擎开始绘制的事件回调（这个可能是vsync信号触发的，后面会详细分析引擎内部的机制），然后就启动了build/layout/paint这个UI渲染流程；</li>
<li>遍历_dirtyElements脏数据列表，执行Element.rebuild，会导致widget重新build；</li>
<li>使用新的widget来更新Element，被修改的Element关联的RenderObject会执行markNeedsLayout，用来标记这个RenderObject需要重新布局，markNeedsLayout会向上遍历parent直到遇到布局边界点，并把作为布局边界点的RenderObject添加到PipelineOwner._nodesNeedingLayout列表中；</li>
<li>遍历_nodesNeedingLayout布局列表，列表中的RenderObject会被执行performLayout()和markNeedsPaint()，performLayout对子树进行布局计算，markNeedsPaint则会递归调用parent，直到遇到绘制边界节点，并把绘制边界节点添加到_nodesNeedingPaint列表中；</li>
<li>遍历_nodesNeedingPaint列表，对子树进行绘制；</li>
</ol>
<pre class="mermaid">

zenuml
State.setState {
    Element.markNeedsBuild {
        &quot;_dirty &#x3D; true&quot;
        BuildOwner.scheduleBuildFor {
            WidgetsBinding._handleBuildScheduled {
                SchedulerBinding.ensureVisualUpdate {
                    SchedulerBinding.scheduleFrame {
                        &quot;确保onBeginFrame&#x2F;onDrawFrame回调已设置&quot;
                        PlatformDispatcher.scheduleFrame {
                            &quot;调用engine的native实现&quot;
                            return
                        }
                    }
                    return
                }
                return
            }
            &quot;_dirtyElements.add(element)&quot;
            &quot;element._inDirtyList &#x3D; true&quot;
            return
        }
        return
    }
}
</pre>

<p>在调度帧刷新任务阶段，最重要的两个工作就是：</p>
<ol>
<li>调用PlatformDispatcher.scheduleFrame，通知引擎要进行下一帧的刷新；</li>
<li>将状态改变的Element添加到<code>BuildOwner._dirtyElements</code>脏列表中。</li>
</ol>
<p>在scheduleFrame执行后，引擎就会在合适的时机先后执行<code>onBeginFrame</code>和<code>onDrawFrame</code>两个回调，比如下个vsync信号到来时。下面是PlatformDispatcher.scheduleFrame()函数的注释：</p>
<blockquote>
<p>Requests that, at the next appropriate opportunity, the [onBeginFrame] and [onDrawFrame] callbacks be invoked.</p>
</blockquote>
<h2 id="帧绘制"><a href="#帧绘制" class="headerlink" title="帧绘制"></a>帧绘制</h2><p>调度阶段之后，就会执行帧的绘制任务，帧的绘制分为如下几个阶段：</p>
<ul>
<li><strong>idle</strong>：空闲阶段。</li>
<li><strong>transientCallbacks</strong>：临时回调执行阶段。对应<code>SchedulerBinding.handleBeginFrame</code>（即，onBeginFrame），会执行通过<code>WidgetsBinding.instance.scheduleFrameCallback</code>注册的回调；</li>
<li><strong>midFrameMicrotasks</strong>：执行临时回调期间注册的Microtasks；</li>
<li><strong>persistentCallbacks</strong>：持久回调执行阶段，持久回调是通过SchedulerBinding.addPersistentFrameCallback来注册。在<code>RendererBinding.initInstances</code>就会注册一个永久回调，此永久回调中会执行<code>RendererBinding.drawFrame()</code>。</li>
<li><strong>postFrameCallbacks</strong>：执行通过SchedulerBinding.addPostFrameCallback注册的回调，这些回调是在一帧渲染完成后被执行。</li>
</ul>
<p>下面是这五个阶段的时序图：</p>
<pre class="mermaid">

zenuml
PlatformDispatcher.onBeginFrame {
    SchedulerBinding.handleBeginFrame {
        &quot;🚩SchedulerPhase.transientCallbacks&quot;
        &quot;🚩SchedulerPhase.midFrameMicrotasks&quot;
        return
    }
}
PlatformDispatcher.onDrawFrame {
    SchedulerBinding.handleDrawFrame {
        &quot;🚩SchedulerPhase.persistentCallbacks&quot; {
            WidgetsBinding.drawFrame
        }
        &quot;🚩SchedulerPhase.postFrameCallbacks&quot;
        &quot;🚩SchedulerPhase.idle&quot;
        return
    }
}
</pre>

<p>其中最重要的就是RendererBinding.drawFrame的执行，build、layout和draw都在这里被执行。下面是<code>WidgetsBinding.drawFrame()</code>的代码实现：</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//WidgetsBinding</span></span><br><span class="line">  <span class="keyword">void</span> drawFrame() &#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="keyword">if</span> (rootElement != <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="comment">//执行build和markNeedsLayout</span></span><br><span class="line">        buildOwner!.buildScope(rootElement!);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">super</span>.drawFrame(); <span class="comment">//RendererBinding.drawFrame()</span></span><br><span class="line">      buildOwner!.finalizeTree();</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;&#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<pre class="mermaid">

zenuml
WidgetsBinding.drawFrame {
    BuildOwner.buildScope {
        &quot;遍历_dirtyElements列表，Element执行rebuild&quot; {
            StatefulElement.&quot;Element.rebuild&quot; {
                &quot;ComponentElement:performRebuild&quot; {
                    build {
                        &quot;state.build(this)&quot;
                    }
                    &quot;Element:updateChild&quot;
                }
            }
        }
    }
    RendererBinding.&quot;super.drawFrame()&quot; {
        PipelineOwner.flushLayout
        PipelineOwner.flushCompositingBits
        PipelineOwner.flushPaint
        return
    }
}
</pre>

<h3 id="buildScope并markNeedsLayout"><a href="#buildScope并markNeedsLayout" class="headerlink" title="buildScope并markNeedsLayout"></a>buildScope并markNeedsLayout</h3><p>首先遍历BuildOwner._dirtyElements列表中Element，调用这些Element的rebuild方法。rebuild会调用到Widget或者State的build方法，如果某个组件需要更新，则其RenderObject.markNeedsLayout会被执行。</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//BuildOwner</span></span><br><span class="line">  <span class="keyword">void</span> buildScope(<span class="built_in">Element</span> context, [ VoidCallback? callback ]) &#123;</span><br><span class="line">    <span class="keyword">if</span> (callback == <span class="keyword">null</span> &amp;&amp; _dirtyElements.isEmpty) &#123;</span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      _scheduledFlushDirtyElements = <span class="keyword">true</span>;</span><br><span class="line">      <span class="comment">//setState时StatefulElement已经被放到这个_dirtyElements列表中了</span></span><br><span class="line">      _dirtyElements.sort(<span class="built_in">Element</span>._sort); </span><br><span class="line">      _dirtyElementsNeedsResorting = <span class="keyword">false</span>;</span><br><span class="line">      <span class="built_in">int</span> dirtyCount = _dirtyElements.length;</span><br><span class="line">      <span class="built_in">int</span> index = <span class="number">0</span>;</span><br><span class="line">      <span class="keyword">while</span> (index &lt; dirtyCount) &#123;</span><br><span class="line">        <span class="keyword">final</span> <span class="built_in">Element</span> element = _dirtyElements[index];</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">          <span class="comment">//执行rebuild，最终会执行到widget的build方法</span></span><br><span class="line">          element.rebuild();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (e, stack) &#123;&#125;</span><br><span class="line">        index += <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">if</span> (dirtyCount &lt; _dirtyElements.length || _dirtyElementsNeedsResorting!) &#123;</span><br><span class="line">          _dirtyElements.sort(<span class="built_in">Element</span>._sort);</span><br><span class="line">          _dirtyElementsNeedsResorting = <span class="keyword">false</span>;</span><br><span class="line">          dirtyCount = _dirtyElements.length;</span><br><span class="line">          <span class="keyword">while</span> (index &gt; <span class="number">0</span> &amp;&amp; _dirtyElements[index - <span class="number">1</span>].dirty) &#123;</span><br><span class="line">            index -= <span class="number">1</span>;</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">      <span class="comment">//清除脏标记，以及清空脏列表</span></span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">final</span> <span class="built_in">Element</span> element <span class="keyword">in</span> _dirtyElements) &#123;</span><br><span class="line">        <span class="keyword">assert</span>(element._inDirtyList);</span><br><span class="line">        element._inDirtyList = <span class="keyword">false</span>;</span><br><span class="line">      &#125;</span><br><span class="line">      _dirtyElements.clear();</span><br><span class="line">      _scheduledFlushDirtyElements = <span class="keyword">false</span>;</span><br><span class="line">      _dirtyElementsNeedsResorting = <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>我们看下<code>element.rebuild()</code>是如何实现的。先看下</p>
<?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="78px" preserveAspectRatio="none" style="width:571px;height:78px;background:#FFFFFF;" version="1.1" viewBox="0 0 571 78" width="571px" zoomAndPan="magnify"><defs/><g><!--class Element--><g id="elem_Element"><rect codeLine="1" fill="#F1F1F1" height="64.2969" id="Element" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="162" x="7" y="7"/><ellipse cx="54.25" cy="23" fill="#A9DCDF" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M56.3281,24.8125 L56.7188,25.7969 L56.3281,25.7969 C55.875,25.7969 55.7656,25.8125 55.6094,25.9219 C55.3594,26.0781 55.2031,26.3594 55.2031,26.6563 C55.2031,26.9219 55.3438,27.1719 55.5625,27.3281 C55.7031,27.4531 55.9063,27.5 56.3281,27.5 L58.6875,27.5 C59.0469,27.5 59.2656,27.4688 59.4063,27.375 C59.6563,27.2344 59.8125,26.9375 59.8125,26.6563 C59.8125,26.375 59.6719,26.125 59.4531,25.9688 C59.2813,25.8281 59.125,25.7969 58.6563,25.7969 L55.2656,17.5938 L51.5938,17.5938 C51.1406,17.5938 51.0156,17.6094 50.8594,17.7031 C50.6094,17.875 50.4531,18.1563 50.4531,18.4375 C50.4531,18.7188 50.5938,18.9688 50.8125,19.1406 C50.9844,19.25 51.1563,19.2813 51.5938,19.2813 L52.6719,19.2813 L50.0313,25.7969 C49.6094,25.7969 49.4531,25.8125 49.2969,25.9219 C49.0469,26.0781 48.8906,26.3594 48.8906,26.6563 C48.8906,27.2188 49.2656,27.5 50.0156,27.5 L52.2813,27.5 C52.6406,27.5 52.8594,27.4688 52.9844,27.375 C53.25,27.2344 53.3906,26.9375 53.3906,26.6563 C53.3906,26.375 53.2656,26.125 53.0469,25.9531 C52.875,25.8281 52.7344,25.7969 52.2813,25.7969 L51.8906,25.7969 L52.2813,24.8125 L56.3281,24.8125 Z M55.625,23.1094 L52.9531,23.1094 L54.2969,19.8438 L55.625,23.1094 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="59" x="74.75" y="27.8467">Element</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="168" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="168" y1="47" y2="47"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="150" x="13" y="63.9951">void rebuild({force})</text></g><!--class ComponentElement--><g id="elem_ComponentElement"><rect codeLine="4" fill="#F1F1F1" height="64.2969" id="ComponentElement" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="174" x="204" y="7"/><ellipse cx="219" cy="23" fill="#A9DCDF" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M221.0781,24.8125 L221.4688,25.7969 L221.0781,25.7969 C220.625,25.7969 220.5156,25.8125 220.3594,25.9219 C220.1094,26.0781 219.9531,26.3594 219.9531,26.6563 C219.9531,26.9219 220.0938,27.1719 220.3125,27.3281 C220.4531,27.4531 220.6563,27.5 221.0781,27.5 L223.4375,27.5 C223.7969,27.5 224.0156,27.4688 224.1563,27.375 C224.4063,27.2344 224.5625,26.9375 224.5625,26.6563 C224.5625,26.375 224.4219,26.125 224.2031,25.9688 C224.0313,25.8281 223.875,25.7969 223.4063,25.7969 L220.0156,17.5938 L216.3438,17.5938 C215.8906,17.5938 215.7656,17.6094 215.6094,17.7031 C215.3594,17.875 215.2031,18.1563 215.2031,18.4375 C215.2031,18.7188 215.3438,18.9688 215.5625,19.1406 C215.7344,19.25 215.9063,19.2813 216.3438,19.2813 L217.4219,19.2813 L214.7813,25.7969 C214.3594,25.7969 214.2031,25.8125 214.0469,25.9219 C213.7969,26.0781 213.6406,26.3594 213.6406,26.6563 C213.6406,27.2188 214.0156,27.5 214.7656,27.5 L217.0313,27.5 C217.3906,27.5 217.6094,27.4688 217.7344,27.375 C218,27.2344 218.1406,26.9375 218.1406,26.6563 C218.1406,26.375 218.0156,26.125 217.7969,25.9531 C217.625,25.8281 217.4844,25.7969 217.0313,25.7969 L216.6406,25.7969 L217.0313,24.8125 L221.0781,24.8125 Z M220.375,23.1094 L217.7031,23.1094 L219.0469,19.8438 L220.375,23.1094 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="142" x="233" y="27.8467">ComponentElement</text><line style="stroke:#181818;stroke-width:0.5;" x1="205" x2="377" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="205" x2="377" y1="47" y2="47"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="158" x="210" y="63.9951">void performRebuild()</text></g><!--class StatefulElement--><g id="elem_StatefulElement"><rect codeLine="7" fill="#F1F1F1" height="64.2969" id="StatefulElement" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="151" x="413.5" y="7"/><ellipse cx="428.5" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M430.8438,18.6719 C429.9063,18.2344 429.3125,18.0938 428.4375,18.0938 C425.8125,18.0938 423.8125,20.1719 423.8125,22.8906 L423.8125,24.0156 C423.8125,26.5938 425.9219,28.4844 428.8125,28.4844 C430.0313,28.4844 431.1875,28.1875 431.9375,27.6406 C432.5156,27.2344 432.8438,26.7813 432.8438,26.3906 C432.8438,25.9375 432.4531,25.5469 431.9844,25.5469 C431.7656,25.5469 431.5625,25.625 431.375,25.8125 C430.9219,26.2969 430.9219,26.2969 430.7344,26.3906 C430.3125,26.6563 429.625,26.7813 428.8594,26.7813 C426.8125,26.7813 425.5156,25.6875 425.5156,23.9844 L425.5156,22.8906 C425.5156,21.1094 426.7656,19.7969 428.5,19.7969 C429.0781,19.7969 429.6875,19.9531 430.1563,20.2031 C430.6406,20.4844 430.8125,20.7031 430.9063,21.1094 C430.9688,21.5156 431,21.6406 431.1406,21.7656 C431.2813,21.9063 431.5156,22.0156 431.7344,22.0156 C432,22.0156 432.2656,21.875 432.4375,21.6563 C432.5469,21.5 432.5781,21.3125 432.5781,20.8906 L432.5781,19.4688 C432.5781,19.0313 432.5625,18.9063 432.4688,18.75 C432.3125,18.4844 432.0313,18.3438 431.7344,18.3438 C431.4375,18.3438 431.2344,18.4375 431.0156,18.75 L430.8438,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="119" x="442.5" y="27.8467">StatefulElement</text><line style="stroke:#181818;stroke-width:0.5;" x1="414.5" x2="563.5" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="414.5" x2="563.5" y1="47" y2="47"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="101" x="419.5" y="63.9951">Widget build()</text></g><!--reverse link Element to ComponentElement--><g id="link_Element_ComponentElement"><path codeLine="10" d="M187.279,39 C198.849,39 192.419,39 203.989,39 " fill="none" id="Element-backto-ComponentElement" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="169.279,39,187.279,45,187.279,33,169.279,39" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link ComponentElement to StatefulElement--><g id="link_ComponentElement_StatefulElement"><path codeLine="11" d="M396.012,39 C407.718,39 401.423,39 413.129,39 " fill="none" id="ComponentElement-backto-StatefulElement" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="378.012,39,396.012,45,396.012,33,378.012,39" style="stroke:#181818;stroke-width:1.0;"/></g><!--SRC=[IqmgBYbAJ2vHSCr9pKtDAr6evb80WhByp1I5ejIaqioS58tgjFoYvDHQJQvQhaIOSkVyt8ByFA06BFeAKek0EdA3eDf1-f9p4ekB5O9B4ajIqqfpKFM4PwQafvOe81J3f6rgT37iuSAm6AGApM00]--></g></svg>

<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Element</span></span><br><span class="line">  <span class="keyword">void</span> rebuild(&#123;<span class="built_in">bool</span> force = <span class="keyword">false</span>&#125;) &#123;</span><br><span class="line">    <span class="keyword">if</span> (_lifecycleState != _ElementLifecycle.active || (!_dirty &amp;&amp; !force)) &#123;</span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      performRebuild();</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;&#125;</span><br><span class="line">  &#125;</span><br><span class="line"><span class="comment">//ComponentElement</span></span><br><span class="line">  <span class="keyword">void</span> performRebuild() &#123;</span><br><span class="line">    Widget? built;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      built = build();</span><br><span class="line">    &#125; <span class="keyword">catch</span> (e, stack) &#123;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">      <span class="comment">// We delay marking the element as clean until after calling build() so</span></span><br><span class="line">      <span class="comment">// that attempts to markNeedsBuild() during build() will be ignored.</span></span><br><span class="line">      <span class="keyword">super</span>.performRebuild(); <span class="comment">// clears the &quot;dirty&quot; flag</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="comment">//更新child配置信息，如果wiget配置项发生了改变，会调用到对应RenderObject的额markNeedsLayout</span></span><br><span class="line">      _child = updateChild(_child, built, slot);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (e, stack) &#123; ... &#125;</span><br><span class="line">  &#125;</span><br><span class="line"><span class="comment">//StatefulElement</span></span><br><span class="line">  <span class="meta">@override</span></span><br><span class="line">  Widget build() =&gt; state.build(<span class="keyword">this</span>); <span class="comment">//调用用户自定义的build生成Widget</span></span><br></pre></td></tr></table></figure>

<p>比如setState更新了一个Text的文本内容，这个Text关联的RenderObject就会调用到<code>RenderObject.markNeedsLayout</code>，用来标记这个RenderObject需要重新布局，markNeedsLayout会向上回溯parent直到遇到布局边界点，并把作为布局边界点的RenderObject添加到<code>PipelineOwner._nodesNeedingLayout</code>列表中。代码如下：</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//RenderObject</span></span><br><span class="line">  <span class="keyword">void</span> markNeedsLayout() &#123;</span><br><span class="line">    <span class="keyword">if</span> (_needsLayout) &#123;</span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (_relayoutBoundary == <span class="keyword">null</span>) &#123;</span><br><span class="line">      _needsLayout = <span class="keyword">true</span>;</span><br><span class="line">      <span class="keyword">if</span> (parent != <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="comment">// _relayoutBoundary is cleaned by an ancestor in RenderObject.layout.</span></span><br><span class="line">        <span class="comment">// Conservatively mark everything dirty until it reaches the closest</span></span><br><span class="line">        <span class="comment">// known relayout boundary.</span></span><br><span class="line">        markParentNeedsLayout();</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (_relayoutBoundary != <span class="keyword">this</span>) &#123;</span><br><span class="line">      <span class="comment">//parent的_needsLayout会设置为true，并调用parent.markNeedsLayout()</span></span><br><span class="line">      <span class="comment">//因此，这句代码的作用是在parent方向上将自身到布局边界路径上的所有节点都标记为需要布局，</span></span><br><span class="line">      <span class="comment">//并且把找到的边界节点添加到PipelineOwner中（见下面的else代码分支）</span></span><br><span class="line">      markParentNeedsLayout();</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">//当前节点就是_relayoutBoundary的情况就会停止向上遍历</span></span><br><span class="line">      _needsLayout = <span class="keyword">true</span>;</span><br><span class="line">      <span class="keyword">if</span> (owner != <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="comment">//添加到PipelineOwner中</span></span><br><span class="line">        owner!._nodesNeedingLayout.add(<span class="keyword">this</span>);</span><br><span class="line">        <span class="comment">//persistentCallbacks阶段，此调用不起任何作用，具体可以看代码实现</span></span><br><span class="line">        owner!.requestVisualUpdate();</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>注意：这里的布局边界和绘制边界的区别。如果每次更新UI要对整个树重新布局，这样无疑会到了很大的性能负担，而布局边界就是为了解决这个问题。什么样的节点是边界节点呢？我们会在layout阶段详细介绍。</p>
<h3 id="flushLayout"><a href="#flushLayout" class="headerlink" title="flushLayout"></a>flushLayout</h3><p>Flutter的布局过程：</p>
<ul>
<li>首先，上层 widget 向下层 widget 传递约束条件；</li>
<li>然后，下层 widget 向上层 widget 传递大小信息。</li>
<li>最后，上层 widget 决定下层 widget 的位置。</li>
</ul>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//PipelineOwner</span></span><br><span class="line">  <span class="keyword">void</span> flushLayout() &#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="keyword">while</span> (_nodesNeedingLayout.isNotEmpty) &#123;</span><br><span class="line">        <span class="keyword">assert</span>(!_shouldMergeDirtyNodes);</span><br><span class="line">        <span class="keyword">final</span> <span class="built_in">List</span>&lt;RenderObject&gt; dirtyNodes = _nodesNeedingLayout;</span><br><span class="line">        _nodesNeedingLayout = &lt;RenderObject&gt;[];</span><br><span class="line">        dirtyNodes.sort((RenderObject a, RenderObject b) =&gt; a.depth - b.depth);</span><br><span class="line">        <span class="keyword">for</span> (<span class="built_in">int</span> i = <span class="number">0</span>; i &lt; dirtyNodes.length; i++) &#123; <span class="comment">//遍历布局列表</span></span><br><span class="line">          <span class="keyword">if</span> (_shouldMergeDirtyNodes) &#123; <span class="comment">//这个我们先不管</span></span><br><span class="line">            _shouldMergeDirtyNodes = <span class="keyword">false</span>;</span><br><span class="line">            <span class="keyword">if</span> (_nodesNeedingLayout.isNotEmpty) &#123;</span><br><span class="line">              _nodesNeedingLayout.addAll(dirtyNodes.getRange(i, dirtyNodes.length));</span><br><span class="line">              <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">          <span class="keyword">final</span> RenderObject node = dirtyNodes[i];</span><br><span class="line">          <span class="keyword">if</span> (node._needsLayout &amp;&amp; node.owner == <span class="keyword">this</span>) &#123;</span><br><span class="line">            <span class="comment">//执行RenderObject的performLayout()和markNeedsPaint()</span></span><br><span class="line">            node._layoutWithoutResize();</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// No need to merge dirty nodes generated from processing the last</span></span><br><span class="line">        <span class="comment">// relayout boundary back.</span></span><br><span class="line">        _shouldMergeDirtyNodes = <span class="keyword">false</span>;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">final</span> PipelineOwner child <span class="keyword">in</span> _children) &#123;</span><br><span class="line">        child.flushLayout();</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">      _shouldMergeDirtyNodes = <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>flushLayout时，会遍历_nodesNeedingLayout列表中的RenderObject，然后执行其performLayout()和markNeedsPaint()。performLayout是在子类中实现，比如RenderPositionedBox.performLayout()的实现如下：</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//RenderPositionedBox</span></span><br><span class="line">  <span class="keyword">void</span> performLayout() &#123;</span><br><span class="line">    <span class="comment">//获取parent传下来的布局约束</span></span><br><span class="line">    <span class="keyword">final</span> BoxConstraints constraints = <span class="keyword">this</span>.constraints;</span><br><span class="line">    <span class="keyword">final</span> <span class="built_in">bool</span> shrinkWrapWidth = _widthFactor != <span class="keyword">null</span> || constraints.maxWidth == <span class="built_in">double</span>.infinity;</span><br><span class="line">    <span class="keyword">final</span> <span class="built_in">bool</span> shrinkWrapHeight = _heightFactor != <span class="keyword">null</span> || constraints.maxHeight == <span class="built_in">double</span>.infinity;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (child != <span class="keyword">null</span>) &#123;</span><br><span class="line">      <span class="comment">//调用child的layout，把布局约束传给child；</span></span><br><span class="line">      <span class="comment">//parentUsesSize为true表示需要依赖child的大小进行布局</span></span><br><span class="line">      child!.layout(constraints.loosen(), parentUsesSize: <span class="keyword">true</span>);</span><br><span class="line">      size = constraints.constrain(Size(</span><br><span class="line">        shrinkWrapWidth ? child!.size.width * (_widthFactor ?? <span class="number">1.0</span>) : <span class="built_in">double</span>.infinity,</span><br><span class="line">        shrinkWrapHeight ? child!.size.height * (_heightFactor ?? <span class="number">1.0</span>) : <span class="built_in">double</span>.infinity,</span><br><span class="line">      ));</span><br><span class="line">      <span class="comment">//计算child的位置，位置放在child!.parentData.offset</span></span><br><span class="line">      alignChild();</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      size = constraints.constrain(Size(</span><br><span class="line">        shrinkWrapWidth ? <span class="number">0.0</span> : <span class="built_in">double</span>.infinity,</span><br><span class="line">        shrinkWrapHeight ? <span class="number">0.0</span> : <span class="built_in">double</span>.infinity,</span><br><span class="line">      ));</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//RenderObject</span></span><br><span class="line">  <span class="keyword">void</span> layout(Constraints constraints, &#123; <span class="built_in">bool</span> parentUsesSize = <span class="keyword">false</span> &#125;) &#123;</span><br><span class="line">    <span class="comment">//判断是否是边界节点：</span></span><br><span class="line">    <span class="comment">//1. parentUsesSize为false，表示当前组件的parent的大小不依赖这个child组件，所以当前组件需要重新布局的时候不需要对parent进行重新布局；</span></span><br><span class="line">    <span class="comment">//2. sizedByParent为true，当前组件的大小只依赖parent的约束，而不受当前组件的子组件大小的影响。比如RenderAndroidView是嵌入的</span></span><br><span class="line">    <span class="comment">//   Android原生View，不可能再嵌套子孙widget的，大小只受父布局的约束；RenderTwoDimensionalViewport也是一个示例场景；</span></span><br><span class="line">    <span class="comment">//3. constraints.isTight严格约束，固定宽高，比如指定宽高的SizedBox</span></span><br><span class="line">    <span class="comment">//4. parent不是RenderObject，只有根组件RenderView没有parent</span></span><br><span class="line">    <span class="keyword">final</span> <span class="built_in">bool</span> isRelayoutBoundary = !parentUsesSize || sizedByParent || constraints.isTight || parent <span class="keyword">is</span>! RenderObject;</span><br><span class="line">    <span class="comment">//如果符合布局边界条件，则使用当前组件为布局边界，否则使用parent的布局边界</span></span><br><span class="line">    <span class="keyword">final</span> RenderObject relayoutBoundary = isRelayoutBoundary ? <span class="keyword">this</span> : parent!._relayoutBoundary!;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (!_needsLayout &amp;&amp; constraints == _constraints) &#123;</span><br><span class="line">      <span class="keyword">if</span> (relayoutBoundary != _relayoutBoundary) &#123;</span><br><span class="line">        <span class="comment">//如果布局边界发生了变化，则递归访问子孙组件，将子孙的_relayoutBoundary设置为新的布局边界；</span></span><br><span class="line">        <span class="comment">//递归终止条件是，子孙组件自身就是边界节点。</span></span><br><span class="line">        _relayoutBoundary = relayoutBoundary;</span><br><span class="line">        visitChildren(_propagateRelayoutBoundaryToChild);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    _constraints = constraints;</span><br><span class="line">    <span class="keyword">if</span> (_relayoutBoundary != <span class="keyword">null</span> &amp;&amp; relayoutBoundary != _relayoutBoundary) &#123;</span><br><span class="line">      <span class="comment">// The local relayout boundary has changed, must notify children in case</span></span><br><span class="line">      <span class="comment">// they also need updating. Otherwise, they will be confused about what</span></span><br><span class="line">      <span class="comment">// their actual relayout boundary is later.</span></span><br><span class="line">      <span class="comment">//递归清除子孙组件的_relayoutBoundary，递归终止条件是子孙组件自身就是边界节点</span></span><br><span class="line">      visitChildren(_cleanChildRelayoutBoundary);</span><br><span class="line">    &#125;</span><br><span class="line">    _relayoutBoundary = relayoutBoundary;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (sizedByParent) &#123;</span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">        performResize();</span><br><span class="line">      &#125; <span class="keyword">catch</span> (e, stack) &#123; ... &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    RenderObject? debugPreviousActiveLayout;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      performLayout(); <span class="comment">//执行布局算法</span></span><br><span class="line">      markNeedsSemanticsUpdate();</span><br><span class="line">    &#125; <span class="keyword">catch</span> (e, stack) &#123; ... &#125;</span><br><span class="line">    _needsLayout = <span class="keyword">false</span>; <span class="comment">//清空布局标记</span></span><br><span class="line">    <span class="comment">//标记是否进行重新绘制，重新绘制的节点会被添加到PipelineOwner._nodesNeedingPaint列表中</span></span><br><span class="line">    markNeedsPaint();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">void</span> markNeedsPaint() &#123;</span><br><span class="line">    <span class="keyword">if</span> (_needsPaint) &#123;</span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    _needsPaint = <span class="keyword">true</span>;</span><br><span class="line">    <span class="comment">// If this was not previously a repaint boundary it will not have</span></span><br><span class="line">    <span class="comment">// a layer we can paint from.</span></span><br><span class="line">    <span class="keyword">if</span> (isRepaintBoundary &amp;&amp; _wasRepaintBoundary) &#123;</span><br><span class="line">      <span class="comment">// If we always have our own layer, then we can just repaint</span></span><br><span class="line">      <span class="comment">// ourselves without involving any other nodes.</span></span><br><span class="line">      <span class="keyword">assert</span>(_layerHandle.layer <span class="keyword">is</span> OffsetLayer);</span><br><span class="line">      <span class="keyword">if</span> (owner != <span class="keyword">null</span>) &#123;</span><br><span class="line">        <span class="comment">//当前节点是绘制边界节点，把边界节点加入到重绘列表中</span></span><br><span class="line">        owner!._nodesNeedingPaint.add(<span class="keyword">this</span>);</span><br><span class="line">        owner!.requestVisualUpdate(); <span class="comment">//idle或postFrameCallbacks阶段会调用scheduleFrame，其他阶段无作用</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (parent <span class="keyword">is</span> RenderObject) &#123;</span><br><span class="line">      <span class="comment">//递归调用parent，直到遇到绘制边界节点</span></span><br><span class="line">      parent!.markNeedsPaint();</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">// If we are the root of the render tree and not a repaint boundary</span></span><br><span class="line">      <span class="comment">// then we have to paint ourselves, since nobody else can paint us.</span></span><br><span class="line">      <span class="comment">// We don&#x27;t add ourselves to _nodesNeedingPaint in this case,</span></span><br><span class="line">      <span class="comment">// because the root is always told to paint regardless.</span></span><br><span class="line">      <span class="comment">//</span></span><br><span class="line">      <span class="comment">// Trees rooted at a RenderView do not go through this</span></span><br><span class="line">      <span class="comment">// code path because RenderViews are repaint boundaries.</span></span><br><span class="line">      <span class="keyword">if</span> (owner != <span class="keyword">null</span>) &#123;</span><br><span class="line">        owner!.requestVisualUpdate();</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>再总结一下，flushLayout阶段会遍历<code>PipelineOwner._nodesNeedingPaint</code>中的RenderObject，然后调用它们的performLayout()和markNeedsPaint()，markNeedsPaint()会把需要绘制的边界节点添加到<code>PipelineOwner._nodesNeedingPaint</code>中。</p>
<h3 id="flushPaint"><a href="#flushPaint" class="headerlink" title="flushPaint"></a>flushPaint</h3><p><code>PipelineOwner.flushPaint</code>会遍历_nodesNeedingPaint</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//PipelineOwner</span></span><br><span class="line">  <span class="keyword">void</span> flushPaint() &#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="keyword">final</span> <span class="built_in">List</span>&lt;RenderObject&gt; dirtyNodes = _nodesNeedingPaint;</span><br><span class="line">      _nodesNeedingPaint = &lt;RenderObject&gt;[]; <span class="comment">//_nodesNeedingPaint赋值为空</span></span><br><span class="line"></span><br><span class="line">      <span class="comment">// Sort the dirty nodes in reverse order (deepest first).</span></span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">final</span> RenderObject node <span class="keyword">in</span> dirtyNodes..sort((RenderObject a, RenderObject b) =&gt; b.depth - a.depth)) &#123;</span><br><span class="line">        <span class="comment">//能够加入_nodesNeedingPaint肯定都是绘制边界节点</span></span><br><span class="line">        <span class="keyword">if</span> ((node._needsPaint || node._needsCompositedLayerUpdate) &amp;&amp; node.owner == <span class="keyword">this</span>) &#123;</span><br><span class="line">          <span class="keyword">if</span> (node._layerHandle.layer!.attached) &#123;</span><br><span class="line">            <span class="keyword">assert</span>(node.isRepaintBoundary);</span><br><span class="line">            <span class="keyword">if</span> (node._needsPaint) &#123;</span><br><span class="line">              PaintingContext.repaintCompositedChild(node); <span class="comment">//内部直接调用_repaintCompositedChild</span></span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">              PaintingContext.updateLayerProperties(node);</span><br><span class="line">            &#125;</span><br><span class="line">          &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            node._skippedPaintingOnLayer();</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">final</span> PipelineOwner child <span class="keyword">in</span> _children) &#123;</span><br><span class="line">        child.flushPaint();</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123; ... &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//PaintingContext的静态函数</span></span><br><span class="line">  <span class="keyword">static</span> <span class="keyword">void</span> _repaintCompositedChild(</span><br><span class="line">    RenderObject child, &#123;</span><br><span class="line">    <span class="built_in">bool</span> debugAlsoPaintedParent = <span class="keyword">false</span>,</span><br><span class="line">    PaintingContext? childContext,</span><br><span class="line">  &#125;) &#123;</span><br><span class="line">    <span class="keyword">assert</span>(child.isRepaintBoundary); <span class="comment">//必须是绘制边界节点</span></span><br><span class="line">    OffsetLayer? childLayer = child._layerHandle.layer <span class="keyword">as</span> OffsetLayer?;</span><br><span class="line">    <span class="keyword">if</span> (childLayer == <span class="keyword">null</span>) &#123;</span><br><span class="line">      <span class="comment">// 为这个绘制边界节点创建一个OffsetLayer，也有可能是OffsetLayer的子类</span></span><br><span class="line">      <span class="keyword">final</span> OffsetLayer layer = child.updateCompositedLayer(oldLayer: <span class="keyword">null</span>);</span><br><span class="line">      child._layerHandle.layer = childLayer = layer;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      childLayer.removeAllChildren();</span><br><span class="line">      <span class="comment">//childLayer不为空的情况，此处返回的必须还是childLayer，后面有个assert来检查</span></span><br><span class="line">      <span class="keyword">final</span> OffsetLayer updatedLayer = child.updateCompositedLayer(oldLayer: childLayer);</span><br><span class="line">      <span class="keyword">assert</span>(identical(updatedLayer, childLayer),</span><br><span class="line">        <span class="string">&#x27;<span class="subst">$child</span> created a new layer instance <span class="subst">$updatedLayer</span> instead of reusing the &#x27;</span></span><br><span class="line">        <span class="string">&#x27;existing layer <span class="subst">$childLayer</span>. See the documentation of RenderObject.updateCompositedLayer &#x27;</span></span><br><span class="line">        <span class="string">&#x27;for more information on how to correctly implement this method.&#x27;</span></span><br><span class="line">      );</span><br><span class="line">    &#125;</span><br><span class="line">    child._needsCompositedLayerUpdate = <span class="keyword">false</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">assert</span>(identical(childLayer, child._layerHandle.layer));</span><br><span class="line">    <span class="keyword">assert</span>(child._layerHandle.layer <span class="keyword">is</span> OffsetLayer); <span class="comment">//必须是OffsetLayer</span></span><br><span class="line"></span><br><span class="line">    childContext ??= PaintingContext(childLayer, child.paintBounds);</span><br><span class="line">    child._paintWithContext(childContext, Offset.zero);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Double-check that the paint method did not replace the layer (the first</span></span><br><span class="line">    <span class="comment">// check is done in the [layer] setter itself).</span></span><br><span class="line">    <span class="keyword">assert</span>(identical(childLayer, child._layerHandle.layer));</span><br><span class="line">    childContext.stopRecordingIfNeeded();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//RenderObject</span></span><br><span class="line">  <span class="keyword">void</span> _paintWithContext(PaintingContext context, Offset offset) &#123;</span><br><span class="line">    <span class="comment">// If we still need layout, then that means that we were skipped in the</span></span><br><span class="line">    <span class="comment">// layout phase and therefore don&#x27;t need painting. We might not know that</span></span><br><span class="line">    <span class="comment">// yet (that is, our layer might not have been detached yet), because the</span></span><br><span class="line">    <span class="comment">// same node that skipped us in layout is above us in the tree (obviously)</span></span><br><span class="line">    <span class="comment">// and therefore may not have had a chance to paint yet (since the tree</span></span><br><span class="line">    <span class="comment">// paints in reverse order). In particular this will happen if they have</span></span><br><span class="line">    <span class="comment">// a different layer, because there&#x27;s a repaint boundary between us.</span></span><br><span class="line">    <span class="keyword">if</span> (_needsLayout) &#123;</span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    RenderObject? debugLastActivePaint;</span><br><span class="line">    _needsPaint = <span class="keyword">false</span>;</span><br><span class="line">    _needsCompositedLayerUpdate = <span class="keyword">false</span>;</span><br><span class="line">    _wasRepaintBoundary = isRepaintBoundary;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="comment">//RenderObject执行paint进行绘制，需要子类来实现paint方法</span></span><br><span class="line">      paint(context, offset);</span><br><span class="line">      <span class="keyword">assert</span>(!_needsLayout); <span class="comment">// check that the paint() method didn&#x27;t mark us dirty again</span></span><br><span class="line">      <span class="keyword">assert</span>(!_needsPaint); <span class="comment">// check that the paint() method didn&#x27;t mark us dirty again</span></span><br><span class="line">    &#125; <span class="keyword">catch</span> (e, stack) &#123;... &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//RenderShiftedBox</span></span><br><span class="line">  <span class="keyword">void</span> paint(PaintingContext context, Offset offset) &#123;</span><br><span class="line">    <span class="keyword">final</span> RenderBox? child = <span class="keyword">this</span>.child;</span><br><span class="line">    <span class="keyword">if</span> (child != <span class="keyword">null</span>) &#123;</span><br><span class="line">      <span class="keyword">final</span> BoxParentData childParentData = child.parentData! <span class="keyword">as</span> BoxParentData;</span><br><span class="line">      context.paintChild(child, childParentData.offset + offset);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>RenderObject.paint需要子类自己实现，我们来看一个简单的样例，来自RenderShiftedBox的实现，它是具备child的节点，所以会递归进行child的绘制：</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//RenderShiftedBox</span></span><br><span class="line">  <span class="keyword">void</span> paint(PaintingContext context, Offset offset) &#123;</span><br><span class="line">    <span class="keyword">final</span> RenderBox? child = <span class="keyword">this</span>.child;</span><br><span class="line">    <span class="keyword">if</span> (child != <span class="keyword">null</span>) &#123;</span><br><span class="line">      <span class="keyword">final</span> BoxParentData childParentData = child.parentData! <span class="keyword">as</span> BoxParentData;</span><br><span class="line">      <span class="comment">//只有一个child，调用paintChild进行绘制</span></span><br><span class="line">      context.paintChild(child, childParentData.offset + offset);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"><span class="comment">//PaintingContext</span></span><br><span class="line">  <span class="keyword">void</span> paintChild(RenderObject child, Offset offset) &#123;</span><br><span class="line">    <span class="keyword">if</span> (child.isRepaintBoundary) &#123;</span><br><span class="line">      stopRecordingIfNeeded();</span><br><span class="line">      <span class="comment">//child是绘制边界节点，会创建新的PaintingContext和OffsetLayer进行绘制</span></span><br><span class="line">      _compositeChild(child, offset);</span><br><span class="line">    <span class="comment">// If a render object was a repaint boundary but no longer is one, this</span></span><br><span class="line">    <span class="comment">// is where the framework managed layer is automatically disposed.</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (child._wasRepaintBoundary) &#123;</span><br><span class="line">      <span class="comment">//child曾经是个绘制边界，但现在已经不是了，则需要取消与Layer的关联</span></span><br><span class="line">      <span class="comment">//如果layer引用计数变为0了，则会调用Layer.dispose来释放资源</span></span><br><span class="line">      child._layerHandle.layer = <span class="keyword">null</span>;</span><br><span class="line">      <span class="comment">//执行child.paint</span></span><br><span class="line">      child._paintWithContext(<span class="keyword">this</span>, offset);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">//执行child.paint</span></span><br><span class="line">      child._paintWithContext(<span class="keyword">this</span>, offset);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>

<p>再来看个真正的绘制，代码示例来自<code>ColoredBox</code>，对应的render object是_RenderColoredBox，绘制代码如下：</p>
<figure class="highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> paint(PaintingContext context, Offset offset) &#123;</span><br><span class="line">  <span class="keyword">if</span> (size &gt; Size.zero) &#123;</span><br><span class="line">    <span class="comment">//使用Canvas进行矩形区域的绘制</span></span><br><span class="line">    context.canvas.drawRect(offset &amp; size, Paint()..color = color);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> (child != <span class="keyword">null</span>) &#123;</span><br><span class="line">    <span class="comment">//child不为空，继续继续child的绘制</span></span><br><span class="line">    context.paintChild(child!, offset);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Canvas绘制"><a href="#Canvas绘制" class="headerlink" title="Canvas绘制"></a>Canvas绘制</h3><?xml version="1.0" encoding="us-ascii" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="418px" preserveAspectRatio="none" style="width:682px;height:418px;background:#FFFFFF;" version="1.1" viewBox="0 0 682 418" width="682px" zoomAndPan="magnify"><defs/><g><!--class Layer--><g id="elem_Layer"><rect codeLine="1" fill="#F1F1F1" height="48" id="Layer" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="72" x="362" y="7"/><ellipse cx="377" cy="23" fill="#A9DCDF" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M379.0781,24.8125 L379.4688,25.7969 L379.0781,25.7969 C378.625,25.7969 378.5156,25.8125 378.3594,25.9219 C378.1094,26.0781 377.9531,26.3594 377.9531,26.6563 C377.9531,26.9219 378.0938,27.1719 378.3125,27.3281 C378.4531,27.4531 378.6563,27.5 379.0781,27.5 L381.4375,27.5 C381.7969,27.5 382.0156,27.4688 382.1563,27.375 C382.4063,27.2344 382.5625,26.9375 382.5625,26.6563 C382.5625,26.375 382.4219,26.125 382.2031,25.9688 C382.0313,25.8281 381.875,25.7969 381.4063,25.7969 L378.0156,17.5938 L374.3438,17.5938 C373.8906,17.5938 373.7656,17.6094 373.6094,17.7031 C373.3594,17.875 373.2031,18.1563 373.2031,18.4375 C373.2031,18.7188 373.3438,18.9688 373.5625,19.1406 C373.7344,19.25 373.9063,19.2813 374.3438,19.2813 L375.4219,19.2813 L372.7813,25.7969 C372.3594,25.7969 372.2031,25.8125 372.0469,25.9219 C371.7969,26.0781 371.6406,26.3594 371.6406,26.6563 C371.6406,27.2188 372.0156,27.5 372.7656,27.5 L375.0313,27.5 C375.3906,27.5 375.6094,27.4688 375.7344,27.375 C376,27.2344 376.1406,26.9375 376.1406,26.6563 C376.1406,26.375 376.0156,26.125 375.7969,25.9531 C375.625,25.8281 375.4844,25.7969 375.0313,25.7969 L374.6406,25.7969 L375.0313,24.8125 L379.0781,24.8125 Z M378.375,23.1094 L375.7031,23.1094 L377.0469,19.8438 L378.375,23.1094 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="40" x="391" y="27.8467">Layer</text><line style="stroke:#181818;stroke-width:0.5;" x1="363" x2="433" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="363" x2="433" y1="47" y2="47"/></g><!--class Picture--><g id="elem_Picture"><rect codeLine="2" fill="#F1F1F1" height="48" id="Picture" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="81" x="264.5" y="239"/><ellipse cx="279.5" cy="255" fill="#A9DCDF" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M281.5781,256.8125 L281.9688,257.7969 L281.5781,257.7969 C281.125,257.7969 281.0156,257.8125 280.8594,257.9219 C280.6094,258.0781 280.4531,258.3594 280.4531,258.6563 C280.4531,258.9219 280.5938,259.1719 280.8125,259.3281 C280.9531,259.4531 281.1563,259.5 281.5781,259.5 L283.9375,259.5 C284.2969,259.5 284.5156,259.4688 284.6563,259.375 C284.9063,259.2344 285.0625,258.9375 285.0625,258.6563 C285.0625,258.375 284.9219,258.125 284.7031,257.9688 C284.5313,257.8281 284.375,257.7969 283.9063,257.7969 L280.5156,249.5938 L276.8438,249.5938 C276.3906,249.5938 276.2656,249.6094 276.1094,249.7031 C275.8594,249.875 275.7031,250.1563 275.7031,250.4375 C275.7031,250.7188 275.8438,250.9688 276.0625,251.1406 C276.2344,251.25 276.4063,251.2813 276.8438,251.2813 L277.9219,251.2813 L275.2813,257.7969 C274.8594,257.7969 274.7031,257.8125 274.5469,257.9219 C274.2969,258.0781 274.1406,258.3594 274.1406,258.6563 C274.1406,259.2188 274.5156,259.5 275.2656,259.5 L277.5313,259.5 C277.8906,259.5 278.1094,259.4688 278.2344,259.375 C278.5,259.2344 278.6406,258.9375 278.6406,258.6563 C278.6406,258.375 278.5156,258.125 278.2969,257.9531 C278.125,257.8281 277.9844,257.7969 277.5313,257.7969 L277.1406,257.7969 L277.5313,256.8125 L281.5781,256.8125 Z M280.875,255.1094 L278.2031,255.1094 L279.5469,251.8438 L280.875,255.1094 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="49" x="293.5" y="259.8467">Picture</text><line style="stroke:#181818;stroke-width:0.5;" x1="265.5" x2="344.5" y1="271" y2="271"/><line style="stroke:#181818;stroke-width:0.5;" x1="265.5" x2="344.5" y1="279" y2="279"/></g><!--class PictureRecorder--><g id="elem_PictureRecorder"><rect codeLine="3" fill="#F1F1F1" height="64.2969" id="PictureRecorder" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="177" x="124.5" y="115"/><ellipse cx="153" cy="131" fill="#A9DCDF" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M155.0781,132.8125 L155.4688,133.7969 L155.0781,133.7969 C154.625,133.7969 154.5156,133.8125 154.3594,133.9219 C154.1094,134.0781 153.9531,134.3594 153.9531,134.6563 C153.9531,134.9219 154.0938,135.1719 154.3125,135.3281 C154.4531,135.4531 154.6563,135.5 155.0781,135.5 L157.4375,135.5 C157.7969,135.5 158.0156,135.4688 158.1563,135.375 C158.4063,135.2344 158.5625,134.9375 158.5625,134.6563 C158.5625,134.375 158.4219,134.125 158.2031,133.9688 C158.0313,133.8281 157.875,133.7969 157.4063,133.7969 L154.0156,125.5938 L150.3438,125.5938 C149.8906,125.5938 149.7656,125.6094 149.6094,125.7031 C149.3594,125.875 149.2031,126.1563 149.2031,126.4375 C149.2031,126.7188 149.3438,126.9688 149.5625,127.1406 C149.7344,127.25 149.9063,127.2813 150.3438,127.2813 L151.4219,127.2813 L148.7813,133.7969 C148.3594,133.7969 148.2031,133.8125 148.0469,133.9219 C147.7969,134.0781 147.6406,134.3594 147.6406,134.6563 C147.6406,135.2188 148.0156,135.5 148.7656,135.5 L151.0313,135.5 C151.3906,135.5 151.6094,135.4688 151.7344,135.375 C152,135.2344 152.1406,134.9375 152.1406,134.6563 C152.1406,134.375 152.0156,134.125 151.7969,133.9531 C151.625,133.8281 151.4844,133.7969 151.0313,133.7969 L150.6406,133.7969 L151.0313,132.8125 L155.0781,132.8125 Z M154.375,131.1094 L151.7031,131.1094 L153.0469,127.8438 L154.375,131.1094 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="115" x="170" y="135.8467">PictureRecorder</text><line style="stroke:#181818;stroke-width:0.5;" x1="125.5" x2="300.5" y1="147" y2="147"/><line style="stroke:#181818;stroke-width:0.5;" x1="125.5" x2="300.5" y1="155" y2="155"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="165" x="130.5" y="171.9951">Picture endRecording()</text></g><!--class PictureLayer--><g id="elem_PictureLayer"><rect fill="#F1F1F1" height="48" id="PictureLayer" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="122" x="337" y="123"/><ellipse cx="352" cy="139" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M354.3438,134.6719 C353.4063,134.2344 352.8125,134.0938 351.9375,134.0938 C349.3125,134.0938 347.3125,136.1719 347.3125,138.8906 L347.3125,140.0156 C347.3125,142.5938 349.4219,144.4844 352.3125,144.4844 C353.5313,144.4844 354.6875,144.1875 355.4375,143.6406 C356.0156,143.2344 356.3438,142.7813 356.3438,142.3906 C356.3438,141.9375 355.9531,141.5469 355.4844,141.5469 C355.2656,141.5469 355.0625,141.625 354.875,141.8125 C354.4219,142.2969 354.4219,142.2969 354.2344,142.3906 C353.8125,142.6563 353.125,142.7813 352.3594,142.7813 C350.3125,142.7813 349.0156,141.6875 349.0156,139.9844 L349.0156,138.8906 C349.0156,137.1094 350.2656,135.7969 352,135.7969 C352.5781,135.7969 353.1875,135.9531 353.6563,136.2031 C354.1406,136.4844 354.3125,136.7031 354.4063,137.1094 C354.4688,137.5156 354.5,137.6406 354.6406,137.7656 C354.7813,137.9063 355.0156,138.0156 355.2344,138.0156 C355.5,138.0156 355.7656,137.875 355.9375,137.6563 C356.0469,137.5 356.0781,137.3125 356.0781,136.8906 L356.0781,135.4688 C356.0781,135.0313 356.0625,134.9063 355.9688,134.75 C355.8125,134.4844 355.5313,134.3438 355.2344,134.3438 C354.9375,134.3438 354.7344,134.4375 354.5156,134.75 L354.3438,134.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="90" x="366" y="143.8467">PictureLayer</text><line style="stroke:#181818;stroke-width:0.5;" x1="338" x2="458" y1="155" y2="155"/><line style="stroke:#181818;stroke-width:0.5;" x1="338" x2="458" y1="163" y2="163"/></g><!--class PaintingContext--><g id="elem_PaintingContext"><rect fill="#F1F1F1" height="48" id="PaintingContext" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="150" x="138" y="7"/><ellipse cx="153" cy="23" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M155.3438,18.6719 C154.4063,18.2344 153.8125,18.0938 152.9375,18.0938 C150.3125,18.0938 148.3125,20.1719 148.3125,22.8906 L148.3125,24.0156 C148.3125,26.5938 150.4219,28.4844 153.3125,28.4844 C154.5313,28.4844 155.6875,28.1875 156.4375,27.6406 C157.0156,27.2344 157.3438,26.7813 157.3438,26.3906 C157.3438,25.9375 156.9531,25.5469 156.4844,25.5469 C156.2656,25.5469 156.0625,25.625 155.875,25.8125 C155.4219,26.2969 155.4219,26.2969 155.2344,26.3906 C154.8125,26.6563 154.125,26.7813 153.3594,26.7813 C151.3125,26.7813 150.0156,25.6875 150.0156,23.9844 L150.0156,22.8906 C150.0156,21.1094 151.2656,19.7969 153,19.7969 C153.5781,19.7969 154.1875,19.9531 154.6563,20.2031 C155.1406,20.4844 155.3125,20.7031 155.4063,21.1094 C155.4688,21.5156 155.5,21.6406 155.6406,21.7656 C155.7813,21.9063 156.0156,22.0156 156.2344,22.0156 C156.5,22.0156 156.7656,21.875 156.9375,21.6563 C157.0469,21.5 157.0781,21.3125 157.0781,20.8906 L157.0781,19.4688 C157.0781,19.0313 157.0625,18.9063 156.9688,18.75 C156.8125,18.4844 156.5313,18.3438 156.2344,18.3438 C155.9375,18.3438 155.7344,18.4375 155.5156,18.75 L155.3438,18.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="118" x="167" y="27.8467">PaintingContext</text><line style="stroke:#181818;stroke-width:0.5;" x1="139" x2="287" y1="39" y2="39"/><line style="stroke:#181818;stroke-width:0.5;" x1="139" x2="287" y1="47" y2="47"/></g><!--class Canvas--><g id="elem_Canvas"><rect fill="#F1F1F1" height="48" id="Canvas" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="82" x="7" y="123"/><ellipse cx="22" cy="139" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M24.3438,134.6719 C23.4063,134.2344 22.8125,134.0938 21.9375,134.0938 C19.3125,134.0938 17.3125,136.1719 17.3125,138.8906 L17.3125,140.0156 C17.3125,142.5938 19.4219,144.4844 22.3125,144.4844 C23.5313,144.4844 24.6875,144.1875 25.4375,143.6406 C26.0156,143.2344 26.3438,142.7813 26.3438,142.3906 C26.3438,141.9375 25.9531,141.5469 25.4844,141.5469 C25.2656,141.5469 25.0625,141.625 24.875,141.8125 C24.4219,142.2969 24.4219,142.2969 24.2344,142.3906 C23.8125,142.6563 23.125,142.7813 22.3594,142.7813 C20.3125,142.7813 19.0156,141.6875 19.0156,139.9844 L19.0156,138.8906 C19.0156,137.1094 20.2656,135.7969 22,135.7969 C22.5781,135.7969 23.1875,135.9531 23.6563,136.2031 C24.1406,136.4844 24.3125,136.7031 24.4063,137.1094 C24.4688,137.5156 24.5,137.6406 24.6406,137.7656 C24.7813,137.9063 25.0156,138.0156 25.2344,138.0156 C25.5,138.0156 25.7656,137.875 25.9375,137.6563 C26.0469,137.5 26.0781,137.3125 26.0781,136.8906 L26.0781,135.4688 C26.0781,135.0313 26.0625,134.9063 25.9688,134.75 C25.8125,134.4844 25.5313,134.3438 25.2344,134.3438 C24.9375,134.3438 24.7344,134.4375 24.5156,134.75 L24.3438,134.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="36" y="143.8467">Canvas</text><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="88" y1="155" y2="155"/><line style="stroke:#181818;stroke-width:0.5;" x1="8" x2="88" y1="163" y2="163"/></g><!--class SceneBuilder--><g id="elem_SceneBuilder"><rect codeLine="15" fill="#F1F1F1" height="64.2969" id="SceneBuilder" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="127" x="241.5" y="347"/><ellipse cx="256.5" cy="363" fill="#A9DCDF" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M258.5781,364.8125 L258.9688,365.7969 L258.5781,365.7969 C258.125,365.7969 258.0156,365.8125 257.8594,365.9219 C257.6094,366.0781 257.4531,366.3594 257.4531,366.6563 C257.4531,366.9219 257.5938,367.1719 257.8125,367.3281 C257.9531,367.4531 258.1563,367.5 258.5781,367.5 L260.9375,367.5 C261.2969,367.5 261.5156,367.4688 261.6563,367.375 C261.9063,367.2344 262.0625,366.9375 262.0625,366.6563 C262.0625,366.375 261.9219,366.125 261.7031,365.9688 C261.5313,365.8281 261.375,365.7969 260.9063,365.7969 L257.5156,357.5938 L253.8438,357.5938 C253.3906,357.5938 253.2656,357.6094 253.1094,357.7031 C252.8594,357.875 252.7031,358.1563 252.7031,358.4375 C252.7031,358.7188 252.8438,358.9688 253.0625,359.1406 C253.2344,359.25 253.4063,359.2813 253.8438,359.2813 L254.9219,359.2813 L252.2813,365.7969 C251.8594,365.7969 251.7031,365.8125 251.5469,365.9219 C251.2969,366.0781 251.1406,366.3594 251.1406,366.6563 C251.1406,367.2188 251.5156,367.5 252.2656,367.5 L254.5313,367.5 C254.8906,367.5 255.1094,367.4688 255.2344,367.375 C255.5,367.2344 255.6406,366.9375 255.6406,366.6563 C255.6406,366.375 255.5156,366.125 255.2969,365.9531 C255.125,365.8281 254.9844,365.7969 254.5313,365.7969 L254.1406,365.7969 L254.5313,364.8125 L258.5781,364.8125 Z M257.875,363.1094 L255.2031,363.1094 L256.5469,359.8438 L257.875,363.1094 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="95" x="270.5" y="367.8467">SceneBuilder</text><line style="stroke:#181818;stroke-width:0.5;" x1="242.5" x2="367.5" y1="379" y2="379"/><line style="stroke:#181818;stroke-width:0.5;" x1="242.5" x2="367.5" y1="387" y2="387"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="93" x="247.5" y="403.9951">Scene build()</text></g><!--class Scene--><g id="elem_Scene"><rect codeLine="18" fill="#F1F1F1" height="48" id="Scene" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="76" x="404" y="355"/><ellipse cx="419" cy="371" fill="#A9DCDF" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M421.0781,372.8125 L421.4688,373.7969 L421.0781,373.7969 C420.625,373.7969 420.5156,373.8125 420.3594,373.9219 C420.1094,374.0781 419.9531,374.3594 419.9531,374.6563 C419.9531,374.9219 420.0938,375.1719 420.3125,375.3281 C420.4531,375.4531 420.6563,375.5 421.0781,375.5 L423.4375,375.5 C423.7969,375.5 424.0156,375.4688 424.1563,375.375 C424.4063,375.2344 424.5625,374.9375 424.5625,374.6563 C424.5625,374.375 424.4219,374.125 424.2031,373.9688 C424.0313,373.8281 423.875,373.7969 423.4063,373.7969 L420.0156,365.5938 L416.3438,365.5938 C415.8906,365.5938 415.7656,365.6094 415.6094,365.7031 C415.3594,365.875 415.2031,366.1563 415.2031,366.4375 C415.2031,366.7188 415.3438,366.9688 415.5625,367.1406 C415.7344,367.25 415.9063,367.2813 416.3438,367.2813 L417.4219,367.2813 L414.7813,373.7969 C414.3594,373.7969 414.2031,373.8125 414.0469,373.9219 C413.7969,374.0781 413.6406,374.3594 413.6406,374.6563 C413.6406,375.2188 414.0156,375.5 414.7656,375.5 L417.0313,375.5 C417.3906,375.5 417.6094,375.4688 417.7344,375.375 C418,375.2344 418.1406,374.9375 418.1406,374.6563 C418.1406,374.375 418.0156,374.125 417.7969,373.9531 C417.625,373.8281 417.4844,373.7969 417.0313,373.7969 L416.6406,373.7969 L417.0313,372.8125 L421.0781,372.8125 Z M420.375,371.1094 L417.7031,371.1094 L419.0469,367.8438 L420.375,371.1094 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="44" x="433" y="375.8467">Scene</text><line style="stroke:#181818;stroke-width:0.5;" x1="405" x2="479" y1="387" y2="387"/><line style="stroke:#181818;stroke-width:0.5;" x1="405" x2="479" y1="395" y2="395"/></g><!--class FlutterView--><g id="elem_FlutterView"><rect codeLine="22" fill="#F1F1F1" height="64.2969" id="FlutterView" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="160" x="515" y="347"/><ellipse cx="550.25" cy="363" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M552.5938,358.6719 C551.6563,358.2344 551.0625,358.0938 550.1875,358.0938 C547.5625,358.0938 545.5625,360.1719 545.5625,362.8906 L545.5625,364.0156 C545.5625,366.5938 547.6719,368.4844 550.5625,368.4844 C551.7813,368.4844 552.9375,368.1875 553.6875,367.6406 C554.2656,367.2344 554.5938,366.7813 554.5938,366.3906 C554.5938,365.9375 554.2031,365.5469 553.7344,365.5469 C553.5156,365.5469 553.3125,365.625 553.125,365.8125 C552.6719,366.2969 552.6719,366.2969 552.4844,366.3906 C552.0625,366.6563 551.375,366.7813 550.6094,366.7813 C548.5625,366.7813 547.2656,365.6875 547.2656,363.9844 L547.2656,362.8906 C547.2656,361.1094 548.5156,359.7969 550.25,359.7969 C550.8281,359.7969 551.4375,359.9531 551.9063,360.2031 C552.3906,360.4844 552.5625,360.7031 552.6563,361.1094 C552.7188,361.5156 552.75,361.6406 552.8906,361.7656 C553.0313,361.9063 553.2656,362.0156 553.4844,362.0156 C553.75,362.0156 554.0156,361.875 554.1875,361.6563 C554.2969,361.5 554.3281,361.3125 554.3281,360.8906 L554.3281,359.4688 C554.3281,359.0313 554.3125,358.9063 554.2188,358.75 C554.0625,358.4844 553.7813,358.3438 553.4844,358.3438 C553.1875,358.3438 552.9844,358.4375 552.7656,358.75 L552.5938,358.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="83" x="568.75" y="367.8467">FlutterView</text><line style="stroke:#181818;stroke-width:0.5;" x1="516" x2="674" y1="379" y2="379"/><line style="stroke:#181818;stroke-width:0.5;" x1="516" x2="674" y1="387" y2="387"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="148" x="521" y="403.9951">render(Scene scene)</text></g><!--reverse link Layer to PictureLayer--><g id="link_Layer_PictureLayer"><path codeLine="6" d="M398,73.07 C398,92.848 398,103.196 398,122.965 " fill="none" id="Layer-backto-PictureLayer" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="398,55.07,392,73.07,404,73.07,398,55.07" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link PaintingContext to PictureLayer--><g id="link_PaintingContext_PictureLayer"><path codeLine="7" d="M260.6541,61.3653 C292.7501,81.1433 328.538,103.196 360.618,122.965 " fill="none" id="PaintingContext-backto-PictureLayer" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="250.438,55.07,253.4476,61.623,260.6541,61.3653,257.6445,54.8123,250.438,55.07" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link PaintingContext to PictureRecorder--><g id="link_PaintingContext_PictureRecorder"><path codeLine="8" d="M213,67.07 C213,84.246 213,95.884 213,114.755 " fill="none" id="PaintingContext-backto-PictureRecorder" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="213,55.07,209,61.07,213,67.07,217,61.07,213,55.07" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link PaintingContext to Canvas--><g id="link_PaintingContext_Canvas"><path codeLine="9" d="M169.7371,61.891 C141.1101,81.669 109.953,103.196 81.3406,122.965 " fill="none" id="PaintingContext-backto-Canvas" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="179.61,55.07,172.3999,55.1896,169.7371,61.891,176.9472,61.7715,179.61,55.07" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link Canvas to PictureRecorder--><g id="link_Canvas_PictureRecorder"><path codeLine="10" d="M101.25,147 C112.8516,147 112.453,147 124.055,147 " fill="none" id="Canvas-backto-PictureRecorder" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="89.25,147,95.25,151,101.25,147,95.25,143,89.25,147" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link PictureLayer to Picture--><g id="link_PictureLayer_Picture"><path codeLine="12" d="M371.5944,180.3683 C355.4594,200.1463 339.919,219.196 323.792,238.965 " fill="none" id="PictureLayer-backto-Picture" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="379.18,171.07,372.2878,173.1906,371.5944,180.3683,378.4866,178.2477,379.18,171.07" style="stroke:#181818;stroke-width:1.0;"/></g><!--link PictureRecorder to Picture--><g id="link_PictureRecorder_Picture"><path codeLine="13" d="M238.139,179.151 C253.355,198.005 268.6659,216.9778 282.5449,234.1758 " fill="none" id="PictureRecorder-to-Picture" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="286.313,238.845,283.7736,229.3291,283.1729,234.954,277.548,234.3533,286.313,238.845" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link Picture to SceneBuilder--><g id="link_Picture_SceneBuilder"><path codeLine="19" d="M305,293.07 C305,310.246 305,327.8845 305,346.7548 " fill="none" id="Picture-backto-SceneBuilder" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="305,287.07,301,296.07,305,292.07,309,296.07,305,287.07" style="stroke:#181818;stroke-width:1.0;"/></g><!--link SceneBuilder to Scene--><g id="link_SceneBuilder_Scene"><path codeLine="20" d="M368.684,379 C380.426,379 386.168,379 397.91,379 " fill="none" id="SceneBuilder-to-Scene" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="403.91,379,394.91,375,398.91,379,394.91,383,403.91,379" style="stroke:#181818;stroke-width:1.0;"/></g><!--reverse link Scene to FlutterView--><g id="link_Scene_FlutterView"><path codeLine="25" d="M486.25,379 C497.755,379 503.26,379 514.765,379 " fill="none" id="Scene-backto-FlutterView" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="480.25,379,489.25,383,485.25,379,489.25,375,480.25,379" style="stroke:#181818;stroke-width:1.0;"/></g><!--SRC=[bP3F2i8m3CRlUOeSfz0t61uSUF8m5BntNPJ2wA3D_8FwxdRhgjkS1tj8uSkNxqSY2yTMAaPLIUTmAszaGOx5N2jkBFsGTwHgMvB5Ew1_lOfaoj3HvfGiu0bTDAOF8Q8dm7Af3NjJLXkcA-Fo3qDapteoQSxIGVYyyZK4Gymm5gQh2R5wzwPds2ioj6vqzRb19s7HQjtgSnEHWQdd3ZDW5EZ1mGvXTbCrp6GFcYuzpFfBaqq2qxMrHGvzeg8Znw0N]--></g></svg>

<ul>
<li><code>RenderView.compositeFrame</code>上屏：先通过layer构建Scene，然后再通过<code>FlutterView.render(scene)</code>来渲染，后面的流程就是c++的native流程了。</li>
</ul>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><p><a target="_blank" rel="noopener external nofollow noreferrer" href="https://book.flutterchina.club/chapter14/">Flutter实战·第二版–Flutter核心原理</a><br><a target="_blank" rel="noopener external nofollow noreferrer" href="https://zhuanlan.zhihu.com/p/396509472">Flutter渲染之绘制上屏</a></p>

    </div>

    
    
    

    <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/Flutter/" rel="tag"># Flutter</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/posts/507c84ae.html" rel="prev" title="Flutter三棵树">
                  <i class="fa fa-angle-left"></i> Flutter三棵树
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/posts/7f544006.html" rel="next" title="Flutter Layout过程分析">
                  Flutter Layout过程分析 <i class="fa fa-angle-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">

  <div class="copyright">
    &copy; 
    <span itemprop="copyrightYear">2024</span>
    <span class="with-love">
      <i class="fa fa-heart"></i>
    </span>
    <span class="author" itemprop="copyrightHolder">Jason</span>
  </div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener external nofollow noreferrer" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/pisces/" rel="noopener external nofollow noreferrer" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up fa-lg"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/next-theme-pjax/0.6.0/pjax.min.js" integrity="sha256-vxLn1tSKWD4dqbMRyv940UYw4sXgMtYcK6reefzZrao=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.24/fancybox/fancybox.umd.js" integrity="sha256-oyhjPiYRWGXaAt+ny/mTMWOnN1GBoZDUQnzzgC7FRI4=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.1/search.js" integrity="sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>


  <script class="next-config" data-name="mermaid" type="application/json">{"enable":true,"theme":{"light":"default","dark":"dark"},"js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.5.0/mermaid.min.js","integrity":"sha256-K7oJiQlDulzl24ZUFOywuYme1JqBBvQzK6m8qHjt9Gk="}}</script>
  <script type="module" src="/js/zenuml-definition-074a43fa.js"></script>
  <script type="module" src="/js/mermaid-zenuml.esm.min.mjs"></script>
  <script src="/js/third-party/tags/mermaid.js"></script>


  <script src="/js/third-party/fancybox.js"></script>



  




  

  <script class="next-config" data-name="enableMath" type="application/json">true</script><script class="next-config" data-name="mathjax" type="application/json">{"enable":true,"tags":"none","js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.js","integrity":"sha256-MASABpB4tYktI2Oitl4t+78w/lyA+D7b/s9GEP0JOGI="}}</script>
<script src="/js/third-party/math/mathjax.js"></script>



</body>
</html>
